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

#ifndef MDRV_MVD_PARSER_H

#include <linux/platform_device.h>

#define MDRV_MVD_PARSER_H

#define VPAS_VERSION 20221028
#define MAX_VPAS_NUM      2
#define MAX_META_Q_NUM 256
#define VPAS_BIT_MASK 64
#define PAS_HW_ADDR_UNIT 8

typedef enum {
	///failed
	E_VPAS_FAIL = 0,
	///success
	E_VPAS_OK,
	///invalid parameter
	E_VPAS_RET_INVALID_PARAM,
	//illegal parameter
	E_VPAS_RET_ILLEGAL_ACCESS,
	//
	E_VPAS_RET_INIT_ALREADY_EXIST,
	//
	E_VPAS_RET_INIT_FAIL,
} VPAS_Result;

typedef enum {
	E_VPAS_ERR_NONE,
	E_VPAS_ERR_ALLOC_ION,
	E_VPAS_ERR_GET_DQBUF,
	E_VPAS_ERR_BUF_TASK,
	E_VPAS_ERR_INIT_FAIL,
	E_VPAS_ERR_REGBASE,
	E_VPAS_ERR_LOCK_FAIL,
	E_VPAS_ERR_UNLOCK_FAIL,
	E_VPAS_ERR_TASK_END_FAIL,
	E_VPAS_ERR_MAX,
} VPAS_ErrCode;

typedef enum {
	/* parser id  */
	PARSER_ID_VIDEO_BASE = 0x0000,
	PARSER_ID_0 = PARSER_ID_VIDEO_BASE,
	PARSER_ID_1,
	PARSER_ID_2,
	PARSER_ID_3,
	PARSER_ID_AUDIO_BASE = 0x1000,
	PARSER_ID_10,
	PARSER_ID_11,
	PARSER_ID_12,
	PARSER_ID_13,
	PARSER_ID_14,
	PARSER_ID_15,
	PARSER_ID_16,
	PARSER_ID_17,
} parser_id_enum;

#define E_VPAS_PTS_LEVEL1 1
#define E_VPAS_PTS_LEVEL2 2
#define E_VPAS_PTS_LEVEL3 3
#define E_VPAS_PTS_LEVEL4 4
#define E_VPAS_PTS_LEVEL5 5

#define E_VPAS_PTS_SZ_FACTOR 512

#define E_MI_VPAS_SECURE 0
#define E_MI_VPAS_PATRIAL_DATA 1
#define E_MI_VPAS_PATRIAL_DATA_END 3
#define E_MI_VPAS_I_FRAME 5
#define E_MI_VPAS_GARBAGE_DATA 6
#define E_MI_VPAS_SPS 2

///VPAS driver status
typedef struct _VPAS_DrvStatus {
	bool bIsInit;
} VPAS_DrvStatus;

//-------------------------------------------------------------------------------------------------
//	Function param structure for ioctl
//-------------------------------------------------------------------------------------------------
//MDrv_VPAS_Init
typedef struct {
	parser_id_enum parser_id;
	int es_buf_tag;
	int RegBaseAddr;
	struct dvb2_vb2_ctx *ctx;
} parser_init_config;

//MDrv_VPAS_Exit
typedef struct {
	u8 u8ParserID;
} VPAS_Exit_Param;

typedef struct {
	s32 s32Fd;
	u64 phyEntryOffset;
	u32 szEntrySize;
	u64 u64Pts;
	u8 u8ParserID;
} VPAS_Data_Entry;

typedef struct {
	u32 offset;
	u32 size;
	u64 pts;
	u32 unitType;
	u8 bIFrame;
} VPAS_FRAMING_TBL;
//-------------------------------------------------------------------------------------------------
//	Function and Variable
//-------------------------------------------------------------------------------------------------

enum MPEG_PICTURE_STRUCTURE {
	MPEG_PIC_STRUCTURE_RESERVED,
	MPEG_PIC_STRUCTURE_TOP_FIELD,
	MPEG_PIC_STRUCTURE_BOTTOM_FIELD,
	MPEG_PIC_STRUCTURE_FRAME_PICTURE,
};

typedef enum {
	VPAS_STATE_STOP,
	VPAS_STATE_INIT,
	VPAS_STATE_IDLE,
	VPAS_STATE_RUN,
} video_parser_state;

#define dmx2_fourcc(a, b, c, d)\
	((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24))
#define DMX2_CODEC_VIDEO_MPEG	dmx2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */
#define DMX2_CODEC_VIDEO_HEVC	dmx2_fourcc('H', 'E', 'V', 'C') /* HEVC aka H.265 */
#define DMX2_CODEC_VIDEO_H264	dmx2_fourcc('H', '2', '6', '4') /* H264  */
#define DMX2_CODEC_VIDEO_AVS	dmx2_fourcc('A', 'V', 'S', '0') /* AVS  */
#define DMX2_CODEC_VIDEO_AVS2	dmx2_fourcc('A', 'V', 'S', '2') /* AVS2  */
#define DMX2_CODEC_VIDEO_AVS3	dmx2_fourcc('A', 'V', 'S', '3') /* AVS3  */
#define DMX2_CODEC_VIDEO_VVC	dmx2_fourcc('V', 'V', 'C', '0') /* VVC  */


typedef enum {
	/* set control */
	VPAS_CMD_SET_CONTROL_BASE = 0x0,
	VPAS_CMD_SET_INPUT_MODE,/* in param: value = video_parser_source, default VPAS_SOURCE_DTV.*/
	VPAS_CMD_SET_SECURE,	/* in param: value = pipelie id */
	VPAS_CMD_SET_CLOSE_SECURE, /* in param: value = pipelie id */
	VPAS_CMD_SET_TLV_MODE,	/* in param: value = 0 disable, value = 1 enable, default 0. */
	VPAS_CMD_SET_BYPASS_MODE,/* in param: value = 0 disable, value = 1 enable, default 0. */
	VPAS_CMD_SET_START_OFFSET,/* in param: value = start_offset return 0 fail,1 ok */

	/* get control */
	VPAS_CMD_GET_CONTROL_BASE = 0x1000,
	VPAS_CMD_GET_ES_BUF_INFO,/* In: none.out:ptr=&video_parser_es_buf_info.return 0 fail,1 ok */
	VPAS_CMD_GET_START_OFFSET, /* In: none.out:start_offset. return 0 fail,1 ok */
	VPAS_CMD_GET_READ_OFFSET, /* In: none.out:read_offset. return 0 fail,1 ok */
} video_parser_control_command;

typedef enum {
	VPAS_CALLBACK_SUCCESS,
	VPAS_CALLBACK_FAIL,
} video_parser_callback_status;

typedef enum {
	VPAS_INPUT_MODE_OVERWRITTEN,
	VPAS_INPUT_MODE_DATA_STOPPED,
} video_parser_mode;

typedef struct {
	u64 es_buf_addr;	/* es buffer start address,offset, unit byte */
	u32 es_buf_size;	/* es buffer size, unit byte */
	u64 es_buf_rdptr;	/* es buffer read ptr ,unit byte */
	u64 es_buf_wrptr;	/* es buffer write ptr ,unit byte */
	int es_buf_fd;		/* es buffer dma fd, valid when using dma buf */
	int flag;		/* reverse flag */
} video_parser_es_buf_info;

#define VIDEO_PARSER_ES_MATA_VERSION 0	/* version of es meta structure */
typedef struct {

	u8  version;                    /* version of this structure */
	u8  reserved;                   /* reserved */
	u16 struct_size;                /* size of this structure */
	u32 flag;                       /* extension info of parser */
	u32 pts_flag;                   /* presentation timestamp of current es section */
	u64 pts;                        /* presentation timestamp of current es section */
	u32 es_section_offset;          /* current es section, offset from es_buf_addr, unit byte */
	u32 es_section_length;          /* current es section length, unit byte */
	u64 dataid;                     /* bit 0: secure flag*/
	video_parser_es_buf_info es_buf_info;	/* total es buffer info */
	void *ext_metadata;	/*	 extension meta structure	 */
} parser_es_meta;

typedef struct {
	u32 size;		/* size of control parameter, valid when ptr != NULL */
	union {			/* control parameter */
		u32 value;
		void *ptr;
	};
} vedio_parser_ctrl;

typedef struct {
	video_parser_callback_status status;
} video_parser_callback_param;

enum parser_event {
	PARSER_START,
	PARSER_STOP,
};

typedef int (*video_parser_callback_func)(parser_id_enum parser_id,
	enum parser_event event, void *param);

#ifdef VPAS_PASS_THROUGH_MODE
typedef int (*video_parser_isr_cb)(int irq, void *dev_id);
#endif

int video_parser_init(parser_init_config *p_parser_init, struct platform_device *pdev,
	void *bufctx, struct dmx2_filter *filter, u32 codec_type,
	video_parser_callback_func callback, void *param,
	u32 VPAS_ES_READ_PTR, u32 VPAS_ES_WRITE_PTR, u32 pipeline_id, u8 bEnableParseSlice);
int video_parser_stop(parser_id_enum parser_id);
int video_parser_flush(parser_id_enum parser_id);
int video_parser_suspend(parser_id_enum parser_id);
int video_parser_resume(parser_id_enum parser_id);
int video_parser_get_entry(parser_id_enum parser_id, struct dmx2_ts_video_metadata *p_meta);
int video_parser_update_es_rptr(parser_id_enum parser_id, parser_es_meta *p_meta);
int video_parser_set_control(parser_id_enum parser_id,
	video_parser_control_command cmd, vedio_parser_ctrl *p_ctrl);
int video_parser_get_control(parser_id_enum parser_id, video_parser_control_command cmd,
	vedio_parser_ctrl *p_ctrl);
int video_parser_get_wait_data_count(parser_id_enum parser_id);
int video_parser_deinit(parser_id_enum parser_id);
int video_parser_get_pipeline_id(parser_id_enum parser_id);
int video_parser_isr(int irq, void *dev_id);
int video_parser_qbuf(parser_id_enum parser_id, struct dmx2_buffer *pBuf);
int video_parser_dqbuf(parser_id_enum parser_id, struct dmx2_buffer *pBuf);
int video_parser_print_bank(void);

#ifdef VPAS_PASS_THROUGH_MODE
int video_parser_install_isrcb(video_parser_isr_cb pfn);
#endif

int mtk_dtv_parser_create_sysfs_attr(void *dmxdevice);
int mtk_dtv_parser_remove_sysfs_attr(void *dmxdevice);

//-----------------------------------------------------------------------------
//  Atrace
//-----------------------------------------------------------------------------
#if defined(__KERNEL__) /* Linux Kernel */
#include <linux/mtk-tv-atrace.h>
extern unsigned int atrace_enable;

#define VPAS_ATRACE_BUF_LEN 32

#define VPAS_ATRACE_ASYNC_BEGIN(name, cookie) \
	do {\
		if (atrace_enable == 1) \
			atrace_async_begin(name, cookie);\
	} while (0)
#define VPAS_ATRACE_ASYNC_END(name, cookie) \
	do {\
		if (atrace_enable == 1) \
			atrace_async_end(name, cookie);\
	} while (0)
#define VPAS_ATRACE_BEGIN(name) \
	do {\
		if (atrace_enable == 1) \
			atrace_begin(name);\
	} while (0)
#define VPAS_ATRACE_END(name) \
	do {\
		if (atrace_enable == 1) \
			atrace_end(name);\
	} while (0)
#define VPAS_ATRACE_INT(name, value) \
	do {\
		if (atrace_enable == 1) \
			atrace_int(name, value);\
	} while (0)
#define VPAS_ATRACE_INT_FORMAT(val, format, ...) \
	do {\
		if (atrace_enable == 1) { \
			int snprintf_ret = 0;\
			char m_str[VPAS_ATRACE_BUF_LEN];\
			snprintf_ret = snprintf(m_str, VPAS_ATRACE_BUF_LEN, format, __VA_ARGS__);\
			if (snprintf_ret > 0) \
				atrace_int(m_str, val);\
		} \
	} while (0)
#endif

#endif				/* MDRV_MVD_PARSER_H */
