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

#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/syscalls.h>
#include <linux/types.h>
#include <linux/freezer.h>

#include <linux/dma-buf.h>
#include <linux/ioctl.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/mm.h>
#include <linux/ion.h>
#include <media/dmxdev.h>
#include <media/dvb_demux.h>
#include "mtk_iommu_dtv_api.h"

#include <linux/sysfs.h>
#include <linux/iommu.h>
#include <linux/dma-buf.h>
#include <linux/dvb/dmx2_mtk.h>
#include <linux/vmalloc.h>

#include "mtk_dmx_common.h"
#include "mtk_dmx_dev.h"
#include "mtk_dmx_m2ts.h"
#include "mtk_dmx_pvr.h"
#include "mtk_dmx_rm.h"
#include "mtk_dmx_tm.h"
#include "mtk_dmx_io.h"
#include "mtk_dmx_filter.h"
#include "mtk_dmx_ctrl.h"
#include "mtk_dmx_drv.h"
#include "mtk_dmx_regs.h"
#include "mtk_mad_parser_reg.h"
#include "mtk_mad_parser.h"
#include "mtk_mad_tee_interface.h"


#define PAS_LABEL		"[MDRV_PAS]"
#define DRV_MAD_NAME	"mtk_mad"
#define DRV_MVD_NAME	"mtk_mvd"

#define ENABLE_MAD_MUTEX 1

typedef struct {
	u32 u32rptr;
	u32 u32wptr;
	u32 u32EsWptr[MAX_PTS_NUM];
	u64 u64pts[MAX_PTS_NUM];
	u32 u32ring_flag[MAX_PTS_NUM];
	u32 u32prevEsWptr;
} MAD_PTS_TABLE;
typedef struct {
	u32 u32rptr;
	u32 u32wptr;
	u32 u32seq[MAX_TLV_INFO_NUM];
	u32 u32lng[MAX_TLV_INFO_NUM];
	u32 u32esbytecnt[MAX_TLV_INFO_NUM];
	u32 used_es;
} MAD_TLV_INFO_TABLE;

struct MAD_ES_INFO {
u32 reg_mad_ctrl;
u32 reg_mad_ctrl_wrEn_bit;
u32 reg_es_ctrl;
u32 reg_es_ctrl_freezeLvL_bit;
u32 reg_es_ctrl_updRdCnt_bit;
u32 reg_es_ctrl_clrDramFull_bit;
u32 reg_es_ctrl_clrFifoFull_bit;
u32 reg_es_updCnt;
u32 reg_es_rdCnt;
u32 reg_es_wrCnt;
u32 reg_es_status;
u32 reg_es_status_esDramFull_bit;
u32 reg_es_status_esFifoFull_bit;
u32 reg_es_ptsByteCount_ctrl;
u32 reg_es_ptsByteCount_clr_bit;
u32 reg_pasDma_ctrl;
u32 reg_pas_ctrl;
u32 reg_pas_status;
u32 reg_pts_h;
u32 reg_pts_l;
u32 reg_pts_bytecount_h;
u32 reg_pts_bytecount_l;
};

MAD_TLV_INFO_TBL	dec_tlvTbl[MAX_MAD_NUM];

struct pes_parser_handler {
struct dma_buf *db[MAX_MAD_NUM];
struct dma_buf_attachment *attach[MAX_MAD_NUM];
struct sg_table *sgt[MAX_MAD_NUM];
struct dvb2_vb2_ctx *ctx[MAX_MAD_NUM];
struct platform_device *pdev[MAX_MAD_NUM];
int current_buf_idx[MAX_MAD_NUM];
struct mtk_bc_ctx *buf_ctx[MAX_MAD_NUM];
struct dvb2_buffer	*dvb2_buf[MAX_MAD_NUM];

u64 u64ParserBufAddr[MAX_MAD_NUM];
u32 u32ParserBufSize[MAX_MAD_NUM];
u64 u64TLVBufAddr[MAX_MAD_NUM];
u32 u32TLVBufSize[MAX_MAD_NUM];
s32 s32PasOutputBufFd[MAX_MAD_NUM];
MAD_PTS_TABLE PtsTb[MAX_MAD_NUM];
u16 pts_wridx[MAX_MAD_NUM];
u16 pts_rdidx[MAX_MAD_NUM];
u16 init_flag[MAX_MAD_NUM];
struct dmx2_audio_description meta_info[MAX_MAD_NUM];
struct dmx2_audio_description prev_meta_info[MAX_MAD_NUM];
u16 reg_pas_rdata_sel_mask[MAX_MAD_NUM];
u16 reg_pas_rdata_sel_a2d_str_type[MAX_MAD_NUM];
struct MAD_ES_INFO ES_RegControl[MAX_MAD_NUM];
enum dmx2_main_filter_type filter_type[MAX_MAD_NUM];
bool bMADIsSecure[MAX_MAD_NUM];
u32 buf_tag[MAX_MAD_NUM];
u32 u32es_wrptr[MAX_MAD_NUM];
u32 u32es_find_pts_flag[MAX_MAD_NUM];
u32 u32first_pts_present[MAX_MAD_NUM];
u32 u32thread_es_pollingcnt[MAX_MAD_NUM];
u32 u32thread_pre_es_memcnt[MAX_MAD_NUM];
u32 u32thread_es_memcnt[MAX_MAD_NUM];
u32 u32thread_stop[MAX_MAD_NUM];
struct dmx2_filter *filter[MAX_MAD_NUM];
MAD_TLV_INFO_TABLE stTlvInfoTable[MAX_MAD_NUM];
u16 tlv_wridx_s[MAX_MAD_NUM];
u16 tlv_rdidx_s[MAX_MAD_NUM];
u32 u32secure_es_wrptr[MAX_MAD_NUM];
struct mem_info mad_buffer[MAX_MAD_NUM];
u16 es_accum[MAX_MAD_NUM];
struct dmx2_ts_audio_metadata prev_meta[MAX_MAD_NUM];
struct dmx2_ts_audio_metadata curr_meta[MAX_MAD_NUM];
u64 u64writeEScount[MAX_MAD_NUM];
u8 u8BufOverflow[MAX_MAD_NUM];
u64 u64readEScount[MAX_MAD_NUM];
u32 u32PipeId[MAX_MAD_NUM];
u32 u32writePreEScount[MAX_MAD_NUM];
u16 es_accum2[MAX_MAD_NUM];
};

struct mdrv_pes_parser {
struct platform_device *pdev;
int mad_num;
struct pes_parser_handler *mad;
};

struct mdrv_pes_parser *parser_mad;
u16 secure_flag;
static u16* pTaskArg[MAX_MAD_NUM] = {NULL, NULL, NULL, NULL};
int iBufferFullCnt[MAX_MAD_NUM];

#if ENABLE_MAD_MUTEX
struct mutex stMADMutexLock;
bool bMADMutexInited;

#define _DRV_MAD_LockCreate(_eDevID)                                  \
	do {                                                           \
		if (!bMADMutexInited) { \
			mutex_init(&stMADMutexLock);     \
			bMADMutexInited = true; \
		} \
	} while (0)


#define  _DRV_MAD_Lock(_eDevID)                                                       \
	do {                                                                           \
		mutex_lock( &(stMADMutexLock));    \
	} while (0)


#define _DRV_MAD_UnLock(_eDevID)                                      \
	do {                                                           \
		mutex_unlock(&(stMADMutexLock));    \
	} while (0)

#endif

int mad_pas_log_level = 0x1;
#define DBG_SHOW_SZ 64
#define DBG_STORE_SZ 10

#include <linux/module.h>
#include <linux/timer.h>
#include <linux/jiffies.h>

static struct task_struct *pTask[MAX_MAD_NUM] = {0};

ssize_t mad_pas_help_show(struct device *dev,
	struct device_attribute *attr,
	char *buf)
{
	return snprintf(buf, DBG_SHOW_SZ, "Debug Help:\n");
}

ssize_t mad_pas_log_level_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	return snprintf(buf, DBG_SHOW_SZ, "log_level = %d\n", mad_pas_log_level);
}

ssize_t mad_pas_log_level_store(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{
	unsigned long val;
	int err;

	err = kstrtoul(buf, DBG_STORE_SZ, &val);
	if (err)
		return err;
	if (val > 255)
		return -EINVAL;

	mad_pas_log_level = val;
	return count;
}

DEVICE_ATTR_RO(mad_pas_help);
DEVICE_ATTR_RW(mad_pas_log_level);

struct attribute *mtk_dtv_mad_parser_attrs[] = {
	&dev_attr_mad_pas_help.attr,
	&dev_attr_mad_pas_log_level.attr,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
};

const struct attribute_group mtk_dtv_mad_parser_attr_group = {
	.name = "mtk_dbg_mad_pas",
	.attrs = mtk_dtv_mad_parser_attrs
};

int mtk_dtv_mad_parser_create_sysfs_attr(struct mtk_dmx2dev *dmxdev)
{
	int ret = 0;

	/* Create device attribute files */
	//dev_info (pdev->dev, "Create device attribute files\n");
	ret = sysfs_create_group(&dmxdev->dev->kobj, &mtk_dtv_mad_parser_attr_group);
	if (ret) {
		//dev_err(&pdev->dev, "[%d]Fail to create sysfs files: %d\n", __LINE__, ret);
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "Fail to create sysfs files: %d\n", ret);
	}
	return ret;
}

int mtk_dtv_mad_parser_remove_sysfs_attr(struct mtk_dmx2dev *dmxdev)
{
	/* Remove device attribute files */
	//dev_info (pdev->dev, "Remove device attribute files\n");
	sysfs_remove_group(&dmxdev->dev->kobj, &mtk_dtv_mad_parser_attr_group);

	return 0;
}

u32 MsOS_GetSystemTime (void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0)
    struct    timespec64        ts;
    ktime_get_raw_ts64(&ts);
#else
    struct timespec         ts;
    getrawmonotonic(&ts);
#endif
    return ts.tv_sec* time_1000+ ts.tv_nsec/time_1000000;
}

static bool _MDrv_MAD_Vb2Valid(u16 u16ParserID)
{
	if (parser_mad->mad != NULL && u16ParserID >= 0 && u16ParserID < MAX_MAD_NUM) {
		struct dmx2_filter *filter = parser_mad->mad->filter[u16ParserID];

		if (filter != NULL) {
			struct dvb_fh *fh = filter->fh;

			if (fh != NULL) {
				struct mtk_demux2_fh_ctx *ctx = fh_to_dmxctx(fh);

				if (ctx != NULL) {
					struct mtk_bc_ctx *buf_ctx = fh_dmxctx_get_bc_ctx(ctx);

					if (buf_ctx != NULL) {
						struct dvb2_vb2_ctx *vb2_ctx = &buf_ctx->d_ctx.buf.vb2;

						if (vb2_ctx != NULL) {
							if (dvb2_vb2_is_streaming(vb2_ctx))
								return true;
						}
					}
				}
			}
		}
	}
	return false;
}

u16 _MDrv_MAD_GetExtraHdr(u16 u16ParserID, u16 index)
{
	u16 tmp;

	switch (u16ParserID) {
	case mad_0:
		tmp = MAD_RIU_READ_WORD(REG_PASA_EXTRA_HDR_CTRL)&0xf000;
		tmp |= index;
		MAD_RIU_WRITE_WORD(REG_PASA_EXTRA_HDR_CTRL, tmp);
		return (MAD_RIU_READ_WORD(REG_PASA_STATUS)&0xFF);
	case mad_1:
		tmp = MAD_RIU_READ_WORD(REG_PASB_EXTRA_HDR_CTRL)&0xf000;
		tmp |= index;
		MAD_RIU_WRITE_WORD(REG_PASB_EXTRA_HDR_CTRL, tmp);
		return (MAD_RIU_READ_WORD(REG_PASB_STATUS)&0xFF);
	case mad_2:
		tmp = MAD_RIU_READ_WORD(REG_PASC_EXTRA_HDR_CTRL)&0xf000;
		tmp |= index;
		MAD_RIU_WRITE_WORD(REG_PASC_EXTRA_HDR_CTRL, tmp);
		return (MAD_RIU_READ_WORD(REG_PASC_STATUS)&0xFF);
	case mad_3:
		tmp = MAD_RIU_READ_WORD(REG_PASD_EXTRA_HDR_CTRL)&0xf000;
		tmp |= index;
		MAD_RIU_WRITE_WORD(REG_PASD_EXTRA_HDR_CTRL, tmp);
		return (MAD_RIU_READ_WORD(REG_PASD_STATUS)&0xFF);
	default:
		return 0;
	}
}

u16 _MDrv_MAD_GetStrType(u16 u16ParserID)
{
	u16 tmp;

	switch (u16ParserID) {
	case mad_0:
		tmp = MAD_RIU_READ_WORD(REG_PAS_SELECT)&
			(parser_mad->mad->reg_pas_rdata_sel_mask[u16ParserID]);
		MAD_RIU_WRITE_WORD(REG_PAS_SELECT,
		    (tmp+parser_mad->mad->reg_pas_rdata_sel_a2d_str_type[u16ParserID]));
		return MAD_RIU_READ_WORD(REG_PASA_RDATA_A);
	case mad_1:
		tmp = MAD_RIU_READ_WORD(REG_PAS_SELECT)&
			(parser_mad->mad->reg_pas_rdata_sel_mask[u16ParserID]);
		MAD_RIU_WRITE_WORD(REG_PAS_SELECT,
		    (tmp+parser_mad->mad->reg_pas_rdata_sel_a2d_str_type[u16ParserID]));
		return MAD_RIU_READ_WORD(REG_PASB_RDATA_A);
	case mad_2:
		tmp = MAD_RIU_READ_WORD(REG_PAS_SELECT2)&
			(parser_mad->mad->reg_pas_rdata_sel_mask[u16ParserID]);
		MAD_RIU_WRITE_WORD(REG_PAS_SELECT,
		    (tmp+parser_mad->mad->reg_pas_rdata_sel_a2d_str_type[u16ParserID]));
		return MAD_RIU_READ_WORD(REG_PASC_RDATA_A);
	case mad_3:
		tmp = MAD_RIU_READ_WORD(REG_PAS_SELECT2)&
			(parser_mad->mad->reg_pas_rdata_sel_mask[u16ParserID]);
		MAD_RIU_WRITE_WORD(REG_PAS_SELECT,
		    (tmp+parser_mad->mad->reg_pas_rdata_sel_a2d_str_type[u16ParserID]));
		return MAD_RIU_READ_WORD(REG_PASD_RDATA_A);
	default:
		return 0;
	}
}

u16 _MDrv_MAD_TLV_Parser(u16 u16ParserID)
{
	u32 lng = 0, seq = 0;
	u16 lng_H = 0, lng_L = 0, seq_H = 0, seq_L = 0;
	u32 esWritePtr = 0;
	u16 wridx = 0;

	switch (u16ParserID) {
	case mad_0:
	{
		lng_H = MAD_RIU_READ_WORD(REG_PASA_ISDB_PARSER_LNG_H);
		lng_L = MAD_RIU_READ_WORD(REG_PASA_ISDB_PARSER_LNG_L);
		lng = ((u32)lng_H<<Pts_shift16) + ((u32)lng_L);
		seq_H = MAD_RIU_READ_WORD(REG_PASA_ISDB_PARSER_SEQ_H);
		seq_L = MAD_RIU_READ_WORD(REG_PASA_ISDB_PARSER_SEQ_L);
		seq = ((u32)seq_H<<Pts_shift16) + ((u32)seq_L);

		if (lng && seq) {
			parser_mad->mad->tlv_wridx_s[mad_0]++;
			if (parser_mad->mad->tlv_wridx_s[mad_0] >= MAX_TLV_INFO_NUM)
				parser_mad->mad->tlv_wridx_s[mad_0] = 0;

			wridx = parser_mad->mad->tlv_wridx_s[mad_0];
			parser_mad->mad->stTlvInfoTable[mad_0].u32lng[wridx] = lng;
			parser_mad->mad->stTlvInfoTable[mad_0].u32seq[wridx] = seq;

			esWritePtr  = MAD_RIU_READ_WORD(REG_PASA_ISDB_PARSER_BYTE_COUNT_H);
			esWritePtr <<= Pts_shift16;
			esWritePtr += MAD_RIU_READ_WORD(REG_PASA_ISDB_PARSER_BYTE_COUNT_L);

			if (parser_mad->mad->u32ParserBufSize[mad_0] == 0) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 1 base = 0\n", __func__);
				return 0;
			}

			esWritePtr %= parser_mad->mad->u32ParserBufSize[mad_0];
			parser_mad->mad->stTlvInfoTable[mad_0].u32esbytecnt[wridx] = esWritePtr;
		}
		break;
	}
	case mad_1:
	{
		lng_H = MAD_RIU_READ_WORD(REG_PASB_ISDB_PARSER_LNG_H);
		lng_L = MAD_RIU_READ_WORD(REG_PASB_ISDB_PARSER_LNG_L);
		lng = ((u32)lng_H<<Pts_shift16) + ((u32)lng_L);
		seq_H = MAD_RIU_READ_WORD(REG_PASB_ISDB_PARSER_SEQ_H);
		seq_L = MAD_RIU_READ_WORD(REG_PASB_ISDB_PARSER_SEQ_L);
		seq = ((u32)seq_H<<Pts_shift16) + ((u32)seq_L);

		if (lng && seq) {
			parser_mad->mad->tlv_wridx_s[mad_1]++;
			if (parser_mad->mad->tlv_wridx_s[mad_1] >= MAX_TLV_INFO_NUM)
				parser_mad->mad->tlv_wridx_s[mad_1] = 0;

			wridx = parser_mad->mad->tlv_wridx_s[mad_1];
			parser_mad->mad->stTlvInfoTable[mad_1].u32lng[wridx] = lng;
			parser_mad->mad->stTlvInfoTable[mad_1].u32seq[wridx] = seq;

			esWritePtr  = MAD_RIU_READ_WORD(REG_PASB_ISDB_PARSER_BYTE_COUNT_H);
			esWritePtr <<= Pts_shift16;
			esWritePtr += MAD_RIU_READ_WORD(REG_PASB_ISDB_PARSER_BYTE_COUNT_L);

			if (parser_mad->mad->u32ParserBufSize[mad_1] == 0) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 2 base = 0\n", __func__);
				return 0;
			}

			esWritePtr %= parser_mad->mad->u32ParserBufSize[mad_1];
			parser_mad->mad->stTlvInfoTable[mad_1].u32esbytecnt[wridx] = esWritePtr;
		}
		break;
	}
	case mad_2:
	{
		lng_H = MAD_RIU_READ_WORD(REG_PASC_ISDB_PARSER_LNG_H);
		lng_L = MAD_RIU_READ_WORD(REG_PASC_ISDB_PARSER_LNG_L);
		lng = ((u32)lng_H<<Pts_shift16) + ((u32)lng_L);
		seq_H = MAD_RIU_READ_WORD(REG_PASC_ISDB_PARSER_SEQ_H);
		seq_L = MAD_RIU_READ_WORD(REG_PASC_ISDB_PARSER_SEQ_L);
		seq = ((u32)seq_H<<Pts_shift16) + ((u32)seq_L);

		if (lng && seq) {
			parser_mad->mad->tlv_wridx_s[mad_2]++;
			if (parser_mad->mad->tlv_wridx_s[mad_2] >= MAX_TLV_INFO_NUM)
				parser_mad->mad->tlv_wridx_s[mad_2] = 0;

			wridx = parser_mad->mad->tlv_wridx_s[mad_2];
			parser_mad->mad->stTlvInfoTable[mad_2].u32lng[wridx] = lng;
			parser_mad->mad->stTlvInfoTable[mad_2].u32seq[wridx] = seq;

			esWritePtr  = MAD_RIU_READ_WORD(REG_PASC_ISDB_PARSER_BYTE_COUNT_H);
			esWritePtr <<= Pts_shift16;
			esWritePtr += MAD_RIU_READ_WORD(REG_PASC_ISDB_PARSER_BYTE_COUNT_L);

			if (parser_mad->mad->u32ParserBufSize[mad_2] == 0) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 3 base = 0\n", __func__);
				return 0;
			}

			esWritePtr %= parser_mad->mad->u32ParserBufSize[mad_2];
			parser_mad->mad->stTlvInfoTable[mad_2].u32esbytecnt[wridx] = esWritePtr;
		}
		break;
	}
	case mad_3:
	{
		lng_H = MAD_RIU_READ_WORD(REG_PASD_ISDB_PARSER_LNG_H);
		lng_L = MAD_RIU_READ_WORD(REG_PASD_ISDB_PARSER_LNG_L);
		lng = ((u32)lng_H<<Pts_shift16) + ((u32)lng_L);
		seq_H = MAD_RIU_READ_WORD(REG_PASD_ISDB_PARSER_SEQ_H);
		seq_L = MAD_RIU_READ_WORD(REG_PASD_ISDB_PARSER_SEQ_L);
		seq = ((u32)seq_H<<Pts_shift16) + ((u32)seq_L);

		if (lng && seq) {
			parser_mad->mad->tlv_wridx_s[mad_3]++;
			if (parser_mad->mad->tlv_wridx_s[mad_3] >= MAX_TLV_INFO_NUM)
				parser_mad->mad->tlv_wridx_s[mad_3] = 0;

			wridx = parser_mad->mad->tlv_wridx_s[mad_3];
			parser_mad->mad->stTlvInfoTable[mad_3].u32lng[wridx] = lng;
			parser_mad->mad->stTlvInfoTable[mad_3].u32seq[wridx] = seq;

			esWritePtr  = MAD_RIU_READ_WORD(REG_PASD_ISDB_PARSER_BYTE_COUNT_H);
			esWritePtr <<= Pts_shift16;
			esWritePtr += MAD_RIU_READ_WORD(REG_PASD_ISDB_PARSER_BYTE_COUNT_L);

			if (parser_mad->mad->u32ParserBufSize[mad_3] == 0) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 4 base = 0\n", __func__);
				return 0;
			}

			esWritePtr %= parser_mad->mad->u32ParserBufSize[mad_0];
			parser_mad->mad->stTlvInfoTable[mad_3].u32esbytecnt[wridx] = esWritePtr;
		}
		break;
	}
	default:
		break;
	}

	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s[%d][%x][%x][%x]\n", __func__, u16ParserID, seq, lng,
		esWritePtr);
	return 1;
}

u16 _MDrv_MAD_Parser(u16 u16ParserID)
{
	u64 PTS = 0;
	u16 pts_L = 0, pts_M = 0, pts_H = 0, wridx = 0;
	u32 esWritePtr = 0;

	switch (u16ParserID) {
	case mad_0:
	{
		parser_mad->mad->pts_wridx[mad_0]++;
		if (parser_mad->mad->pts_wridx[mad_0] >= MAX_PTS_NUM)
			parser_mad->mad->pts_wridx[mad_0] = 0;

		wridx = parser_mad->mad->pts_wridx[mad_0];
		pts_H = (MAD_RIU_READ_WORD(REG_PASA_STATUS)>>Pts_shift)&0x1;
		pts_M = MAD_RIU_READ_WORD(REG_PASA_PTS_H);
		pts_L = MAD_RIU_READ_WORD(REG_PASA_PTS_L);
		PTS = ((u64)pts_H<<Pts_shift32) + ((u64)pts_M<<Pts_shift16) + ((u64)pts_L);
		parser_mad->mad->PtsTb[mad_0].u64pts[wridx] = PTS;

		esWritePtr  = MAD_RIU_READ_WORD(REG_PASA_PTS_BYTE_COUNT_H);
		esWritePtr <<= Pts_shift16;
		esWritePtr += MAD_RIU_READ_WORD(REG_PASA_PTS_BYTE_COUNT_L);

		if (parser_mad->mad->u32ParserBufSize[mad_0] == 0) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 1 base = 0\n", __func__);
				return 0;
		}

		esWritePtr %= parser_mad->mad->u32ParserBufSize[mad_0];

		if (esWritePtr < parser_mad->mad->PtsTb[mad_0].u32prevEsWptr)
			parser_mad->mad->PtsTb[mad_0].u32ring_flag[wridx] = 1;
		else
			parser_mad->mad->PtsTb[mad_0].u32ring_flag[wridx] = 0;

		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 1=[%llu][0x%x][%u][%u][%u]\n", __func__, PTS, esWritePtr,
			parser_mad->mad->PtsTb[mad_0].u32ring_flag[wridx],
			parser_mad->mad->PtsTb[mad_0].u32prevEsWptr, wridx);
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "[%u]:[0x%x]\n",
			MsOS_GetSystemTime(), parser_mad->mad->u32es_wrptr[mad_0]);

		parser_mad->mad->PtsTb[mad_0].u32EsWptr[wridx] =
		esWritePtr;
		parser_mad->mad->PtsTb[mad_0].u32prevEsWptr = esWritePtr;
		break;
	}
	case mad_1:
	{
		parser_mad->mad->pts_wridx[mad_1]++;
		if (parser_mad->mad->pts_wridx[mad_1] >= MAX_PTS_NUM)
			parser_mad->mad->pts_wridx[mad_1] = 0;

		wridx = parser_mad->mad->pts_wridx[mad_1];
		pts_H = (MAD_RIU_READ_WORD(REG_PASB_STATUS)>>Pts_shift)&0x1;
		pts_M = MAD_RIU_READ_WORD(REG_PASB_PTS_H);
		pts_L = MAD_RIU_READ_WORD(REG_PASB_PTS_L);
		PTS = ((u64)pts_H<<Pts_shift32) + ((u64)pts_M<<Pts_shift16) + ((u64)pts_L);
		parser_mad->mad->PtsTb[mad_1].u64pts[wridx] = PTS;

		esWritePtr = MAD_RIU_READ_WORD(REG_PASB_PTS_BYTE_COUNT_H);
		esWritePtr <<= Pts_shift16;
		esWritePtr += MAD_RIU_READ_WORD(REG_PASB_PTS_BYTE_COUNT_L);

		if (parser_mad->mad->u32ParserBufSize[mad_1] == 0) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 2 base = 0\n", __func__);
				return 0;
		}

		esWritePtr %= parser_mad->mad->u32ParserBufSize[mad_1];

		if (esWritePtr < parser_mad->mad->PtsTb[mad_1].u32prevEsWptr)
			parser_mad->mad->PtsTb[mad_1].u32ring_flag[wridx] = 1;
		else
			parser_mad->mad->PtsTb[mad_1].u32ring_flag[wridx] = 0;

		parser_mad->mad->PtsTb[mad_1].u32EsWptr[wridx] =
			esWritePtr;
		parser_mad->mad->PtsTb[mad_1].u32prevEsWptr = esWritePtr;
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 2=[%llu][0x%x][%u][%u][%u]\n",
			__func__, PTS, esWritePtr,
			parser_mad->mad->PtsTb[mad_1].u32ring_flag[wridx],
			parser_mad->mad->PtsTb[mad_1].u32prevEsWptr, wridx);
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "[%u]:[0x%x]\n",
			MsOS_GetSystemTime(), parser_mad->mad->u32es_wrptr[mad_1]);
		break;
	}
	case mad_2:
	{
		parser_mad->mad->pts_wridx[mad_2]++;
		if (parser_mad->mad->pts_wridx[mad_2] >= MAX_PTS_NUM)
			parser_mad->mad->pts_wridx[mad_2] = 0;

		wridx = parser_mad->mad->pts_wridx[mad_2];
		pts_H = (MAD_RIU_READ_WORD(REG_PASC_STATUS)>>Pts_shift)&0x1;
		pts_M = MAD_RIU_READ_WORD(REG_PASC_PTS_H);
		pts_L = MAD_RIU_READ_WORD(REG_PASC_PTS_L);
		PTS = ((u64)pts_H<<Pts_shift32) + ((u64)pts_M<<Pts_shift16) + ((u64)pts_L);
		parser_mad->mad->PtsTb[mad_2].u64pts[wridx] = PTS;

		esWritePtr = MAD_RIU_READ_WORD(REG_PASC_PTS_BYTE_COUNT_H);
		esWritePtr <<= Pts_shift16;
		esWritePtr += MAD_RIU_READ_WORD(REG_PASC_PTS_BYTE_COUNT_L);

		if (parser_mad->mad->u32ParserBufSize[mad_2] == 0) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 3 base = 0\n", __func__);
				return 0;
		}

		esWritePtr %= parser_mad->mad->u32ParserBufSize[mad_2];


		if (esWritePtr < parser_mad->mad->PtsTb[mad_2].u32prevEsWptr)
			parser_mad->mad->PtsTb[mad_2].u32ring_flag[wridx] = 1;
		else
			parser_mad->mad->PtsTb[mad_2].u32ring_flag[wridx] = 0;

		parser_mad->mad->PtsTb[mad_2].u32EsWptr[wridx] =
			esWritePtr;
		parser_mad->mad->PtsTb[mad_2].u32prevEsWptr = esWritePtr;
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 3=[%llu][0x%x][%u][%u][%u]\n",
			__func__, PTS, esWritePtr,
			parser_mad->mad->PtsTb[mad_2].u32ring_flag[wridx],
			parser_mad->mad->PtsTb[mad_2].u32prevEsWptr, wridx);
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "[%u]:[0x%x]\n",
			MsOS_GetSystemTime(), parser_mad->mad->u32es_wrptr[mad_2]);
		break;
	}
	case mad_3:
	{
		parser_mad->mad->pts_wridx[mad_3]++;
		if (parser_mad->mad->pts_wridx[mad_3] >= MAX_PTS_NUM)
			parser_mad->mad->pts_wridx[mad_3] = 0;

		wridx = parser_mad->mad->pts_wridx[mad_3];
		pts_H = (MAD_RIU_READ_WORD(REG_PASD_STATUS)>>Pts_shift)&0x1;
		pts_M = MAD_RIU_READ_WORD(REG_PASD_PTS_H);
		pts_L = MAD_RIU_READ_WORD(REG_PASD_PTS_L);
		PTS = ((u64)pts_H<<Pts_shift32) + ((u64)pts_M<<Pts_shift16) + ((u64)pts_L);
		parser_mad->mad->PtsTb[mad_3].u64pts[wridx] = PTS;

		esWritePtr = MAD_RIU_READ_WORD(REG_PASD_PTS_BYTE_COUNT_H);
		esWritePtr <<= Pts_shift16;
		esWritePtr += MAD_RIU_READ_WORD(REG_PASD_PTS_BYTE_COUNT_L);

		if (parser_mad->mad->u32ParserBufSize[mad_3] == 0) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 4 base = 0\n", __func__);
				return 0;
		}

		esWritePtr %= parser_mad->mad->u32ParserBufSize[mad_3];

		if (esWritePtr < parser_mad->mad->PtsTb[mad_3].u32prevEsWptr)
			parser_mad->mad->PtsTb[mad_3].u32ring_flag[wridx] = 1;
		else
			parser_mad->mad->PtsTb[mad_3].u32ring_flag[wridx] = 0;

		parser_mad->mad->PtsTb[mad_3].u32EsWptr[wridx] =
			esWritePtr;
		parser_mad->mad->PtsTb[mad_3].u32prevEsWptr = esWritePtr;
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s PTS 4=[%llu][0x%x][%u][%u][%u]\n",
			__func__, PTS, esWritePtr,
			parser_mad->mad->PtsTb[mad_3].u32ring_flag[wridx],
			parser_mad->mad->PtsTb[mad_3].u32prevEsWptr, wridx);
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "[%u]:[0x%x]\n",
			MsOS_GetSystemTime(), parser_mad->mad->u32es_wrptr[mad_3]);
		break;
	}
	default:
		break;
	}

	return 1;
}

void _MDrv_MAD_SetCtrl(void)
{
#ifndef AUDIO_MERAK20_FLAG
	MAD_RIU_WRITE_WORD(REG_PAS_SOURCE_SELECT, 0x0000);
#endif
}
int mad_ringbuffer(u16 parser_id, u32 *pts_present, u64 *timestamp,
u32 *es_memcnt, u16 pts_wridx, u16 pts_rdidx)
{
	u16 pts_wridx_tmp;
	u32 es_memcnt_tmp;

	*pts_present = 0;
	es_memcnt_tmp = *es_memcnt;
	*es_memcnt =
	parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx]
	+ (parser_mad->mad->u32ParserBufSize[parser_id] -
	parser_mad->mad->u32es_wrptr[parser_id]); //ring

	if (es_memcnt_tmp < *es_memcnt) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "42 es = [%u][%u]\n", *es_memcnt,
		es_memcnt_tmp);
		parser_mad->mad->pts_rdidx[parser_id]++;
		if (parser_mad->mad->pts_rdidx[parser_id] >= MAX_PTS_NUM)
			parser_mad->mad->pts_rdidx[parser_id] = 0;
		parser_mad->mad->u32thread_pre_es_memcnt[parser_id] = 0;
		return -1;
	}

	if (es_memcnt_tmp >=
	(parser_mad->mad->u32ParserBufSize[parser_id]>>1)) {
		parser_mad->mad->u32thread_pre_es_memcnt[parser_id] = 0;
		*pts_present = 0;
		*timestamp = 0;
		parser_mad->mad->pts_rdidx[parser_id]++;
		parser_mad->mad->u32es_find_pts_flag[parser_id] = 0;

		if (parser_mad->mad->pts_rdidx[parser_id] >= MAX_PTS_NUM)
			parser_mad->mad->pts_rdidx[parser_id] = 0;
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "888 %u %u %llu\n",
		es_memcnt_tmp, *es_memcnt, *timestamp);
		return 1;
	}

	pts_wridx_tmp = pts_wridx;
	if ((parser_mad->mad->pts_wridx[parser_id] - pts_wridx_tmp) != 0) {
		pts_wridx_tmp++;
		if (pts_wridx_tmp >= MAX_PTS_NUM)
			pts_wridx_tmp = 0;
		if (parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx_tmp] >=
		parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx]) {
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id] =
			parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx_tmp]
			- parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx];
		} else {
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id] =
			parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx_tmp]
			+ (parser_mad->mad->u32ParserBufSize[parser_id] -
			parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx]);
		}
		if (parser_mad->mad->u32thread_pre_es_memcnt[parser_id] >
		(es_memcnt_tmp - *es_memcnt)) {
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id] =
			es_memcnt_tmp - *es_memcnt;
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "302 %u\n",
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id]);
		}
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "30 es = [%u][%u][%u][%u]\n",
		*es_memcnt, parser_mad->mad->u32es_wrptr[parser_id],
		parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx],
		parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx_tmp]);
	} else
		parser_mad->mad->u32thread_pre_es_memcnt[parser_id] =
		es_memcnt_tmp - *es_memcnt;

	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "33 es = [%u][%u][%u][%u]\n", *es_memcnt,
	parser_mad->mad->u32es_wrptr[parser_id],
	parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx],
	parser_mad->mad->u32thread_pre_es_memcnt[parser_id]);
	parser_mad->mad->u32es_find_pts_flag[parser_id] = 1;
	return 0;
}
int mad_normalbuffer(u16 parser_id, u32 *pts_present, u64 *timestamp,
u32 *es_memcnt, u16 pts_wridx, u16 pts_rdidx)
{
	u16 pts_wridx_tmp;
	u32 es_memcnt_tmp;

	*pts_present = 0;
	es_memcnt_tmp = *es_memcnt;
	*es_memcnt = parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx]
	- parser_mad->mad->u32es_wrptr[parser_id];

	if (es_memcnt_tmp < *es_memcnt) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "42 es = [%u][%u]\n", *es_memcnt,
		es_memcnt_tmp);
		parser_mad->mad->pts_rdidx[parser_id]++;
		if (parser_mad->mad->pts_rdidx[parser_id] >= MAX_PTS_NUM)
			parser_mad->mad->pts_rdidx[parser_id] = 0;
		parser_mad->mad->u32thread_pre_es_memcnt[parser_id] = 0;
		return -1;
	}

	if (es_memcnt_tmp >=
	(parser_mad->mad->u32ParserBufSize[parser_id]>>1)) {
		parser_mad->mad->u32thread_pre_es_memcnt[parser_id] = 0;

		*pts_present = 0;
		*timestamp = 0;
		parser_mad->mad->pts_rdidx[parser_id]++;
		parser_mad->mad->u32es_find_pts_flag[parser_id] = 0;

		if (parser_mad->mad->pts_rdidx[parser_id] >= MAX_PTS_NUM)
			parser_mad->mad->pts_rdidx[parser_id] = 0;
		return 1;
	}

	pts_wridx_tmp = pts_wridx;
	if ((parser_mad->mad->pts_wridx[parser_id] - pts_wridx_tmp) != 0) {
		pts_wridx_tmp++;
		if (pts_wridx_tmp >= MAX_PTS_NUM)
			pts_wridx_tmp = 0;
		if (parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx_tmp] >=
		parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx]){
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id] =
			parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx_tmp]
			- parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx];
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "400 %u\n",
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id]);
		} else {
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id] =
			parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx_tmp]
			+ (parser_mad->mad->u32ParserBufSize[parser_id] -
			parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx]);
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "401 %u\n",
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id]);
		}
		if (parser_mad->mad->u32thread_pre_es_memcnt[parser_id] >
		(es_memcnt_tmp - *es_memcnt)) {
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id] =
			es_memcnt_tmp - *es_memcnt;
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "402 %u\n",
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id]);
		}
	} else
		parser_mad->mad->u32thread_pre_es_memcnt[parser_id] =
		es_memcnt_tmp - *es_memcnt;

	parser_mad->mad->u32thread_es_pollingcnt[parser_id]++;
	parser_mad->mad->u32es_find_pts_flag[parser_id] = 1;
	return 0;
}

void MAD_ptsidx_check(u16 *idx)
{
	if (*idx >= MAX_PTS_NUM)
		*idx = 0;
}

int audio_parser_get_entry(u16 parser_id, struct dmx2_ts_audio_metadata *p_meta, u32 es_memcnt)
{
	int ret = 0, ret2 = 0;
	u16 pts_wridx, pts_rdidx;

	if (p_meta == NULL) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "%s meta is NULL\n", __func__);
		return -EINVAL;
	}
	if (parser_id >= MAX_MAD_NUM) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "id: %d fail\n", parser_id);
		return -EINVAL;
	}

	pts_wridx = parser_mad->mad->pts_wridx[parser_id];
	pts_rdidx = parser_mad->mad->pts_rdidx[parser_id];
	//p_meta->version = MAD_PARSER_ES_MATA_VERSION;
	if (pts_wridx - pts_rdidx != 0)
	{
		pts_wridx = pts_rdidx+1;
		MAD_ptsidx_check(&pts_wridx);
	}
	if (pts_rdidx == pts_wridx) {
		if (parser_mad->mad->u32thread_es_pollingcnt[parser_id] < 1) {
			if (parser_mad->mad->u32thread_es_pollingcnt[parser_id] == 0)
				parser_mad->mad->u32thread_pre_es_memcnt[parser_id] = es_memcnt;
			parser_mad->mad->u32thread_es_pollingcnt[parser_id]++;
			return 0;
		}
		es_memcnt = parser_mad->mad->u32thread_pre_es_memcnt[parser_id];
		parser_mad->mad->u32thread_pre_es_memcnt[parser_id] = 0;
		p_meta->pts_present = 0;
	} else if ((parser_mad->mad->u32first_pts_present[parser_id] == 0) &&
		(parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx] == 0)) {
		u32 es_memcnt_tmp = 0;
		u16 pts_wridx_tmp = 0;
		p_meta->pts_present = 1;
		p_meta->timestamp =
		parser_mad->mad->PtsTb[parser_id].u64pts[pts_wridx];
		parser_mad->mad->pts_rdidx[parser_id]++;
		MAD_ptsidx_check(&parser_mad->mad->pts_rdidx[parser_id]);
		parser_mad->mad->u32es_find_pts_flag[parser_id] = 0;

		pts_wridx_tmp = pts_wridx + 1;
		MAD_ptsidx_check(&pts_wridx_tmp);

		if (parser_mad->mad->pts_wridx[parser_id] >= (pts_wridx_tmp)) {
			es_memcnt_tmp = parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx_tmp] -
				parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx];
			es_memcnt = (es_memcnt > es_memcnt_tmp) ? es_memcnt_tmp : es_memcnt;
		}
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "2 es = [%u][%u]\n",
		es_memcnt, parser_mad->mad->u32es_wrptr[parser_id]);
	} else {
		if (parser_mad->mad->u32es_find_pts_flag[parser_id] == 0) {
			u32 pts_present = 0;
			u64 timestamp = 0;

			if (parser_mad->mad->PtsTb[parser_id].u32EsWptr[pts_wridx] <
			parser_mad->mad->u32es_wrptr[parser_id]) {
				ret2 = mad_ringbuffer(parser_id, &pts_present, &timestamp,
				&es_memcnt,	pts_wridx, pts_rdidx);
				p_meta->pts_present = pts_present;
				p_meta->timestamp = timestamp;
				if (ret2 == -1)
					return 0;
				else if (ret2 == 1)
					goto output;
			} else {
				ret2 = mad_normalbuffer(parser_id, &pts_present, &timestamp,
				&es_memcnt, pts_wridx, pts_rdidx);
				p_meta->pts_present = pts_present;
				p_meta->timestamp = timestamp;
				if (ret2 == -1)
					return 0;
				else if (ret2 == 1)
					goto output;
			}
		} else {
			p_meta->pts_present = 1;
			p_meta->timestamp =
			parser_mad->mad->PtsTb[parser_id].u64pts[pts_wridx];
			parser_mad->mad->u32es_find_pts_flag[parser_id] = 0;

			es_memcnt = parser_mad->mad->u32thread_pre_es_memcnt[parser_id];
			parser_mad->mad->u32thread_pre_es_memcnt[parser_id]  = 0;

			parser_mad->mad->pts_rdidx[parser_id]++;
			MAD_ptsidx_check(&parser_mad->mad->pts_rdidx[parser_id]);
			parser_mad->mad->u32first_pts_present[parser_id] = 1;
		}
	}

	if (es_memcnt >=parser_mad->mad->u32ParserBufSize[parser_id]) {
		parser_mad->mad->u32thread_pre_es_memcnt[parser_id] = 0;
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "6 Valid es mem = [%u][%u][%u]\n", es_memcnt,
		parser_mad->mad->u32es_wrptr[parser_id],
		parser_mad->mad->u32thread_pre_es_memcnt[parser_id]);
	}

output:
	parser_mad->mad->u32thread_es_pollingcnt[parser_id] = 0;
	if (es_memcnt == 0)
		return 0;
	p_meta->data_offset = parser_mad->mad->u32es_wrptr[parser_id];
	p_meta->reserved[0] = es_memcnt;
	p_meta->reserved[reg_2] = parser_mad->mad->u8BufOverflow[parser_id];

	parser_mad->mad->u32es_wrptr[parser_id] += es_memcnt;
	parser_mad->mad->u32es_wrptr[parser_id] %= parser_mad->mad->u32ParserBufSize[parser_id];

	p_meta->ad.version_text_tag = 0;

	if ((_MDrv_MAD_GetExtraHdr(parser_id, Extraheaderparam0) != Extraheader) ||
	(_MDrv_MAD_GetExtraHdr(parser_id, Extraheaderparam1) != Extraheader2)) {
		if (parser_mad->mad->prev_meta[parser_id].ad_present == 1) {
			p_meta->ad.fade = parser_mad->mad->prev_meta[parser_id].ad.fade;
			p_meta->ad.pan =  parser_mad->mad->prev_meta[parser_id].ad.pan;
			p_meta->ad.gain_center =
				parser_mad->mad->prev_meta[parser_id].ad.gain_center;
			p_meta->ad.gain_front = parser_mad->mad->prev_meta[parser_id].ad.gain_front;
			p_meta->ad.gain_surround =
				parser_mad->mad->prev_meta[parser_id].ad.gain_surround;
			p_meta->ad_present = 1;
			goto pan_fade_end;
		} else {
			p_meta->ad_present = 0;
			goto pan_fade_end;
		}
	}

	parser_mad->mad->curr_meta[parser_id].ad.fade = _MDrv_MAD_GetExtraHdr(parser_id, Extraheaderparam2);
	parser_mad->mad->curr_meta[parser_id].ad.pan = _MDrv_MAD_GetExtraHdr(parser_id, Extraheaderparam3);
	if (_MDrv_MAD_GetExtraHdr(parser_id, Extraheaderparam7) == Extraheader3) {
		parser_mad->mad->curr_meta[parser_id].ad.gain_center = _MDrv_MAD_GetExtraHdr(parser_id, Extraheaderparam4);
		parser_mad->mad->curr_meta[parser_id].ad.gain_front = _MDrv_MAD_GetExtraHdr(parser_id, Extraheaderparam5);
		parser_mad->mad->curr_meta[parser_id].ad.gain_surround = _MDrv_MAD_GetExtraHdr(parser_id, Extraheaderparam6);
	} else {
		parser_mad->mad->curr_meta[parser_id].ad.gain_center = parser_mad->mad->prev_meta[parser_id].ad.gain_center;
		parser_mad->mad->curr_meta[parser_id].ad.gain_front = parser_mad->mad->prev_meta[parser_id].ad.gain_front;
		parser_mad->mad->curr_meta[parser_id].ad.gain_surround = parser_mad->mad->prev_meta[parser_id].ad.gain_surround;
	}

	p_meta->ad.fade = parser_mad->mad->curr_meta[parser_id].ad.fade;
	p_meta->ad.pan =  parser_mad->mad->curr_meta[parser_id].ad.pan;
	p_meta->ad.gain_center = parser_mad->mad->curr_meta[parser_id].ad.gain_center;
	p_meta->ad.gain_front = parser_mad->mad->curr_meta[parser_id].ad.gain_front;
	p_meta->ad.gain_surround = parser_mad->mad->curr_meta[parser_id].ad.gain_surround;
	p_meta->ad_present = 1;
	parser_mad->mad->prev_meta[parser_id].ad.fade = parser_mad->mad->curr_meta[parser_id].ad.fade;
	parser_mad->mad->prev_meta[parser_id].ad.pan = parser_mad->mad->curr_meta[parser_id].ad.pan;
	parser_mad->mad->prev_meta[parser_id].ad.gain_center = parser_mad->mad->curr_meta[parser_id].ad.gain_center;
	parser_mad->mad->prev_meta[parser_id].ad.gain_front = parser_mad->mad->curr_meta[parser_id].ad.gain_front;
	parser_mad->mad->prev_meta[parser_id].ad.gain_surround = parser_mad->mad->curr_meta[parser_id].ad.gain_surround;
	parser_mad->mad->prev_meta[parser_id].ad_present = 1;

pan_fade_end:
	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "AD type [%d] = [%d][%d][%d][%d][%d][%d]\n",
	parser_id, p_meta->ad_present, p_meta->ad.fade, p_meta->ad.pan,
	p_meta->ad.gain_center, p_meta->ad.gain_front, p_meta->ad.gain_surround);
	ret = 1;

	switch (parser_id) {
	case mad_0:
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_12_, _BIT_12_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_12_, 0);
		break;
	case mad_1:
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_12_, _BIT_12_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_12_, 0);
		break;
	case mad_2:
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_12_, _BIT_12_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_12_, 0);
		break;
	case mad_3:
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_12_, _BIT_12_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_12_, 0);
		break;
	default:
		break;
	}
	return ret;
}

int audio_parser_isr(int irq, void *dev_id)
{
	int pts_int = 0;

	pts_int = MAD_RIU_READ_WORD(REG_PAS_PTS_INT)&0xF;

	if ((pts_int&0x1) == 1) {
		if (!(parser_mad == NULL || parser_mad->mad == NULL || parser_mad->mad->init_flag[mad_0] == 0))
		{
			if (parser_mad->mad->filter_type[mad_0] == DMX2_FILTER_TYPE_TLV){
				_MDrv_MAD_TLV_Parser(mad_0);
			}else {
				_MDrv_MAD_Parser(mad_0);
			}
		}
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND_1, _BIT_0_, _BIT_0_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND_1, _BIT_0_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_5_, _BIT_5_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_5_, 0x0000);
	}

	if (((pts_int>>Bitshift1)&0x1) == 1) {
		if (!(parser_mad == NULL || parser_mad->mad == NULL || parser_mad->mad->init_flag[mad_1] == 0))
		{
			if (parser_mad->mad->filter_type[mad_1] == DMX2_FILTER_TYPE_TLV){
				_MDrv_MAD_TLV_Parser(mad_1);
			}else {
				_MDrv_MAD_Parser(mad_1);
			}
		}
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND_1, _BIT_0_, _BIT_0_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND_1, _BIT_0_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_5_, _BIT_5_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_5_, 0x0000);
	}

	if (((pts_int>>Bitshift2)&0x1) == 1) {
		if (!(parser_mad == NULL || parser_mad->mad == NULL || parser_mad->mad->init_flag[mad_2] == 0))
		{
			if (parser_mad->mad->filter_type[mad_2] == DMX2_FILTER_TYPE_TLV){
				_MDrv_MAD_TLV_Parser(mad_2);
			}else {
				_MDrv_MAD_Parser(mad_2);
			}
		}
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND_1, _BIT_0_, _BIT_0_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND_1, _BIT_0_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_5_, _BIT_5_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_5_, 0x0000);
	}

	if (((pts_int>>Bitshift3)&0x1) == 1) {
		if (!(parser_mad == NULL || parser_mad->mad == NULL || parser_mad->mad->init_flag[mad_3] == 0))
		{
			if (parser_mad->mad->filter_type[mad_3] == DMX2_FILTER_TYPE_TLV){
				_MDrv_MAD_TLV_Parser(mad_3);
			}else {
				_MDrv_MAD_Parser(mad_3);
			}
		}
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND_1, _BIT_0_, _BIT_0_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND_1, _BIT_0_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_5_, _BIT_5_);
		udelay(sleeptime);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_5_, 0x0000);
	}
	return 1;
}

parser_drv_result _mad_exit(int idx)
{
	parser_drv_result drv_ret = PAS_RESULT_OK;

	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s =[%d]\n", __func__, idx);

	return drv_ret;
}

parser_drv_result _mad_start(u16 u16ParserID)
{
	parser_drv_result drv_ret = PAS_RESULT_OK;
	struct parser_create_param create_param;

	memset(&create_param, 0, sizeof(create_param));

	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s =[%d][%d]\n", __func__, u16ParserID,parser_mad->mad->filter_type[u16ParserID]);

	switch (u16ParserID) {
	case mad_0:
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_7_, _BIT_7_);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_MCU_CTRL, 0x0001, 0x0001);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_ES1_CTRL, _BIT_15_, _BIT_15_);
		MAD_RIU_WRITE_WORD(REG_PAS_SELECT, 0x0000);
		_MDrv_MAD_SetCtrl();
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL_1, _BIT_15_, 0x0000); //setting start
		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV){
			MAD_RIU_WRITE_WORD(REG_PASA_DMA_DRAM_H,
				(((parser_mad->mad->u64TLVBufAddr[u16ParserID]) >> Bitshift4)
				>> Bitshift16));
			MAD_RIU_WRITE_WORD(REG_PASA_DMA_DRAM_L,
				(((parser_mad->mad->u64TLVBufAddr[u16ParserID]) >> Bitshift4)
				& BitMask16));
			MAD_RIU_WRITE_WORD(REG_PASA_DMA_DRAM_SIZE,
				((parser_mad->mad->u32TLVBufSize[u16ParserID]) >> Bitshift4));
		}else{
			MAD_RIU_WRITE_WORD(REG_PASA_DMA_DRAM_H,
				(((parser_mad->mad->u64ParserBufAddr[u16ParserID]) >> Bitshift4)
				>> Bitshift16));
			MAD_RIU_WRITE_WORD(REG_PASA_DMA_DRAM_L,
				(((parser_mad->mad->u64ParserBufAddr[u16ParserID]) >> Bitshift4)
				& BitMask16));
			MAD_RIU_WRITE_WORD(REG_PASA_DMA_DRAM_SIZE,
				((parser_mad->mad->u32ParserBufSize[u16ParserID]) >> Bitshift4));
		}
		MAD_RIU_WRITE_WORD(REG_PASA_DMA_DRAM_OVERRUN_THRESHOLD,
			((parser_mad->mad->u32ParserBufSize[u16ParserID]) >> 1));
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_MIU_BURST_LENGTH, BusrtlengthMask,
			_BIT_1_ | _BIT_0_);

		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_2_, _BIT_2_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_14_, _BIT_14_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_14_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_0_, _BIT_0_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_10_, _BIT_10_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL_1, _BIT_15_ | _BIT_9_,
			_BIT_15_ | _BIT_9_);
		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV) {
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND, _BIT_0_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND_1, _BIT_7_ | _BIT_2_, _BIT_7_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_0_ , _BIT_0_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND, _BIT_1_, _BIT_1_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND, _BIT_1_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND_1, _BIT_0_, _BIT_0_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND_1, _BIT_0_, 0x0000);
		} else {
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND, _BIT_0_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND_1, _BIT_7_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_0_ , 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND, _BIT_0_, _BIT_0_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL_2ND, _BIT_0_, 0x0000);
		}

		MAD_RIU_MASK_WRITE_WORD(REG_PAS_AB_PTS_BYTE_CTRL, _BIT_2_, _BIT_2_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_AB_PTS_BYTE_CTRL, _BIT_2_, 0x0000);

		MAD_RIU_MASK_WRITE_WORD(REG_MAD_MCU_CTRL, BitMask8,
			_BIT_3_ | _BIT_2_ | _BIT_1_ | _BIT_0_);
		MAD_RIU_WRITE_WORD(REG_MAD_CTRL, _BIT_15_ | _BIT_8_ | _BIT_7_);

		MAD_RIU_WRITE_WORD(REG_PASA_STREAM_ID1, StreamID1);
		MAD_RIU_WRITE_WORD(REG_PASA_STREAM_ID2, StreamID2);
		if (secure_flag == 1) {
			struct _ST_AUDIO_SECURE_INFO param;
			int ret = 0;

			param.u8SvpEnableFlag = 1;
			param.u32pipelineID = parser_mad->mad->u32PipeId[u16ParserID];
			param.u16ParserId = u16ParserID;
			param.u8Version = 0x1;
			ret = mad_parser_tee_setmode(u16ParserID, &param);
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s =[%d]\n", __func__, ret);
		}
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_EXTRA_HDR_CTRL, _BIT_14_ | _BIT_13_,
			_BIT_14_ | _BIT_13_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, ParserControlMask,
			_BIT_14_ | _BIT_9_ | _BIT_4_);

		MAD_RIU_WRITE_WORD(REG_MAD_CTRL, _BIT_15_ | _BIT_8_);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_CTRL, 0x0001, 0x00001);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_CTRL, 0x0001, 0x00000);

        if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV){
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_EXTRA_HDR_CTRL, _BIT_14_ | _BIT_13_, 0x0000);

			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_15_| _BIT_14_| _BIT_10_| _BIT_9_ , _BIT_15_| _BIT_9_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_4_ , _BIT_4_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_7_ | _BIT_4_ | _BIT_1_ , _BIT_1_);
		}else{
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_4_ , _BIT_4_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_4_ | _BIT_3_ | _BIT_2_, 0x0000);
        }
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_12_, _BIT_12_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_12_, 0);

		parser_mad->mad->reg_pas_rdata_sel_mask[mad_0] = ParserRdataSelMask1;
		parser_mad->mad->reg_pas_rdata_sel_a2d_str_type[mad_0] = REG_PASA_SELECT_STR_TYPE;

              mdelay(1);
		//Start parser
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_7_, 0);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_2_, 0);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_AB_PTS_BYTE_CTRL, _BIT_2_, 0);
		break;
	case mad_1:
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_7_, _BIT_7_);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_MCU_CTRL, _BIT_1_, _BIT_1_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_ES2_CTRL, _BIT_15_, _BIT_15_);
		MAD_RIU_WRITE_WORD(REG_PAS_SELECT, 0x0000);
		_MDrv_MAD_SetCtrl();
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL_1, _BIT_15_, 0x0000);
		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV){
			MAD_RIU_WRITE_WORD(REG_PASB_DMA_DRAM_H,
				(((parser_mad->mad->u64TLVBufAddr[u16ParserID]) >> Bitshift4)
				>> Bitshift16));
			MAD_RIU_WRITE_WORD(REG_PASB_DMA_DRAM_L,
				(((parser_mad->mad->u64TLVBufAddr[u16ParserID]) >> Bitshift4)
				& BitMask16));
			MAD_RIU_WRITE_WORD(REG_PASB_DMA_DRAM_SIZE,
				((parser_mad->mad->u32TLVBufSize[u16ParserID]) >> Bitshift4));
		}else{
			MAD_RIU_WRITE_WORD(REG_PASB_DMA_DRAM_H,
				(((parser_mad->mad->u64ParserBufAddr[u16ParserID]) >> Bitshift4)
				>> Bitshift16));
			MAD_RIU_WRITE_WORD(REG_PASB_DMA_DRAM_L,
				(((parser_mad->mad->u64ParserBufAddr[u16ParserID]) >> Bitshift4)
				& BitMask16));
			MAD_RIU_WRITE_WORD(REG_PASB_DMA_DRAM_SIZE,
				((parser_mad->mad->u32ParserBufSize[u16ParserID]) >> Bitshift4));
		}
		MAD_RIU_WRITE_WORD(REG_PASB_DMA_DRAM_OVERRUN_THRESHOLD,
			((parser_mad->mad->u32ParserBufSize[u16ParserID]) >> 1));
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_MIU_BURST_LENGTH, BusrtlengthMask,
			_BIT_1_ | _BIT_0_);

		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_2_, _BIT_2_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_14_, _BIT_14_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_14_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_0_, _BIT_0_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_10_, _BIT_10_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL_1, _BIT_15_ | _BIT_9_,
			_BIT_15_ | _BIT_9_);

		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV) {
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND, _BIT_0_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND_1, _BIT_7_ | _BIT_2_, _BIT_7_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_0_ , _BIT_0_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND, _BIT_1_, _BIT_1_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND, _BIT_1_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND_1, _BIT_0_, _BIT_0_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND_1, _BIT_0_, 0x0000);
		} else {
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND, _BIT_0_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND_1, _BIT_7_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_0_ , 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND, _BIT_0_, _BIT_0_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL_2ND, _BIT_0_, 0x0000);
		}

		MAD_RIU_MASK_WRITE_WORD(REG_PAS_AB_PTS_BYTE_CTRL, _BIT_3_, _BIT_3_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_AB_PTS_BYTE_CTRL, _BIT_3_, 0x0000);

		MAD_RIU_MASK_WRITE_WORD(REG_MAD_MCU_CTRL, BitMask8,
			_BIT_3_ | _BIT_2_ | _BIT_1_ | _BIT_0_);
		MAD_RIU_WRITE_WORD(REG_MAD_CTRL, _BIT_15_ | _BIT_8_ | _BIT_7_);

		MAD_RIU_WRITE_WORD(REG_PASB_STREAM_ID1, StreamID1);
		MAD_RIU_WRITE_WORD(REG_PASB_STREAM_ID2, StreamID2);
		if (secure_flag == 1) {
			struct _ST_AUDIO_SECURE_INFO param;
			int ret = 0;

			param.u8SvpEnableFlag = 1;
			param.u32pipelineID = parser_mad->mad->u32PipeId[u16ParserID];
			param.u16ParserId = u16ParserID;
			param.u8Version = 0x1;
			ret = mad_parser_tee_setmode(u16ParserID, &param);
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s =[%d]\n", __func__, ret);
		}
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_EXTRA_HDR_CTRL, _BIT_14_ | _BIT_13_,
			_BIT_14_ | _BIT_13_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, ParserControlMask,
			_BIT_14_ | _BIT_9_ | _BIT_4_);

		MAD_RIU_WRITE_WORD(REG_MAD_CTRL, _BIT_15_ | _BIT_8_);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_CTRL, 0x0001, 0x00001);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_CTRL, 0x0001, 0x00000);

		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV){
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_EXTRA_HDR_CTRL, _BIT_14_ | _BIT_13_, 0x0000);

			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_15_| _BIT_14_| _BIT_10_| _BIT_9_ , _BIT_15_| _BIT_9_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_4_ , _BIT_4_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_7_ | _BIT_4_ | _BIT_1_ , _BIT_1_);
		}else{
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_4_ , _BIT_4_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_4_ | _BIT_3_ | _BIT_2_, 0x0000);
        }
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_12_, _BIT_12_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_12_, 0);

		parser_mad->mad->reg_pas_rdata_sel_mask[mad_1] = ParserRdataSelMask2;
		parser_mad->mad->reg_pas_rdata_sel_a2d_str_type[mad_1] = REG_PASB_SELECT_STR_TYPE;

		mdelay(1);
		//Start parser
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_7_, 0);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_2_, 0);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_AB_PTS_BYTE_CTRL, _BIT_3_, 0);
		break;
	case mad_2:
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_7_, _BIT_7_);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_MCU_CTRL, _BIT_2_, _BIT_2_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_ES3_CTRL, _BIT_15_, _BIT_15_);
		MAD_RIU_WRITE_WORD(REG_PAS_SELECT, 0x0000);
		_MDrv_MAD_SetCtrl();
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL_1, _BIT_15_, 0x0000);
		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV){
			MAD_RIU_WRITE_WORD(REG_PASC_DMA_DRAM_H,
				(((parser_mad->mad->u64TLVBufAddr[u16ParserID]) >> Bitshift4)
				>> Bitshift16));
			MAD_RIU_WRITE_WORD(REG_PASC_DMA_DRAM_L,
				(((parser_mad->mad->u64TLVBufAddr[u16ParserID]) >> Bitshift4)
				& BitMask16));
			MAD_RIU_WRITE_WORD(REG_PASC_DMA_DRAM_SIZE,
				((parser_mad->mad->u32TLVBufSize[u16ParserID]) >> Bitshift4));
		}else{
			MAD_RIU_WRITE_WORD(REG_PASC_DMA_DRAM_H,
				(((parser_mad->mad->u64ParserBufAddr[u16ParserID]) >> Bitshift4)
				>> Bitshift16));
			MAD_RIU_WRITE_WORD(REG_PASC_DMA_DRAM_L,
				(((parser_mad->mad->u64ParserBufAddr[u16ParserID]) >> Bitshift4)
				& BitMask16));
			MAD_RIU_WRITE_WORD(REG_PASC_DMA_DRAM_SIZE,
				((parser_mad->mad->u32ParserBufSize[u16ParserID]) >> Bitshift4));
		}
		MAD_RIU_WRITE_WORD(REG_PASC_DMA_DRAM_OVERRUN_THRESHOLD,
			((parser_mad->mad->u32ParserBufSize[u16ParserID]) >> 1));
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_MIU_BURST_LENGTH, BusrtlengthMask,
			_BIT_1_ | _BIT_0_);

		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_2_, _BIT_2_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_14_, _BIT_14_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_14_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, 0x0001, 0x0001);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_10_, _BIT_10_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL_1, _BIT_15_ | _BIT_9_,
			_BIT_15_ | _BIT_9_);

		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV) {
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND, _BIT_0_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND_1, _BIT_7_ | _BIT_2_, _BIT_7_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_0_ , _BIT_0_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND, _BIT_1_, _BIT_1_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND, _BIT_1_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND_1, _BIT_0_, _BIT_0_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND_1, _BIT_0_, 0x0000);
		} else {
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND, _BIT_0_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND_1, _BIT_7_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_0_ , 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND, _BIT_0_, _BIT_0_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL_2ND, _BIT_0_, 0x0000);
		}

		MAD_RIU_MASK_WRITE_WORD(REG_PAS_CD_PTS_BYTE_CTRL, _BIT_2_, _BIT_2_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_CD_PTS_BYTE_CTRL, _BIT_2_, 0x0000);

		MAD_RIU_MASK_WRITE_WORD(REG_MAD_MCU_CTRL, BitMask8,
			_BIT_3_ | _BIT_2_ | _BIT_1_ | _BIT_0_);
		MAD_RIU_WRITE_WORD(REG_MAD_CTRL2, _BIT_15_ | _BIT_8_ | _BIT_7_);

		MAD_RIU_WRITE_WORD(REG_PASC_STREAM_ID1, StreamID1);
		MAD_RIU_WRITE_WORD(REG_PASC_STREAM_ID2, StreamID2);
		if (secure_flag == 1) {
			struct _ST_AUDIO_SECURE_INFO param;
			int ret = 0;

			param.u8SvpEnableFlag = 1;
			param.u32pipelineID = parser_mad->mad->u32PipeId[u16ParserID];
			param.u16ParserId = u16ParserID;
			param.u8Version = 0x1;
			ret = mad_parser_tee_setmode(u16ParserID, &param);
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s =[%d]\n", __func__, ret);
		}
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_EXTRA_HDR_CTRL, _BIT_14_ | _BIT_13_,
			_BIT_14_ | _BIT_13_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, ParserControlMask,
			_BIT_14_ | _BIT_9_ | _BIT_4_);

		MAD_RIU_WRITE_WORD(REG_MAD_CTRL2, _BIT_15_ | _BIT_8_);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_CTRL2, 0x0001, 0x00001);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_CTRL2, 0x0001, 0x00000);

		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV){
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_EXTRA_HDR_CTRL, _BIT_14_ | _BIT_13_, 0x0000);

			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_15_| _BIT_14_| _BIT_10_| _BIT_9_ , _BIT_15_| _BIT_9_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_4_ , _BIT_4_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_7_ | _BIT_4_ | _BIT_1_ , _BIT_1_);
		}else{
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_4_ , _BIT_4_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_4_ | _BIT_3_ | _BIT_2_, 0x0000);
        }

		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_12_, _BIT_12_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_12_, 0);

		parser_mad->mad->reg_pas_rdata_sel_mask[mad_2] = ParserRdataSelMask1;
		parser_mad->mad->reg_pas_rdata_sel_a2d_str_type[mad_2] = REG_PASC_SELECT_STR_TYPE;

		mdelay(1);
		//Start parser
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_7_, 0);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_2_, 0);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_CD_PTS_BYTE_CTRL, 0x0001, 0);
		break;
	case mad_3:
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_7_, _BIT_7_);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_MCU_CTRL, _BIT_3_, _BIT_3_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_ES4_CTRL, _BIT_15_, _BIT_15_);
		MAD_RIU_WRITE_WORD(REG_PAS_SELECT2, 0x0000);
		_MDrv_MAD_SetCtrl();
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL_1, _BIT_15_, 0x0000);
		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV){
			MAD_RIU_WRITE_WORD(REG_PASD_DMA_DRAM_H,
				(((parser_mad->mad->u64TLVBufAddr[u16ParserID]) >> Bitshift4)
				>> Bitshift16));
			MAD_RIU_WRITE_WORD(REG_PASD_DMA_DRAM_L,
				(((parser_mad->mad->u64TLVBufAddr[u16ParserID]) >> Bitshift4)
				& BitMask16));
			MAD_RIU_WRITE_WORD(REG_PASD_DMA_DRAM_SIZE,
				((parser_mad->mad->u32TLVBufSize[u16ParserID]) >> Bitshift4));
		}else{
			MAD_RIU_WRITE_WORD(REG_PASD_DMA_DRAM_H,
				(((parser_mad->mad->u64ParserBufAddr[u16ParserID]) >> Bitshift4)
				>> Bitshift16));
			MAD_RIU_WRITE_WORD(REG_PASD_DMA_DRAM_L,
				(((parser_mad->mad->u64ParserBufAddr[u16ParserID]) >> Bitshift4)
				& BitMask16));
			MAD_RIU_WRITE_WORD(REG_PASD_DMA_DRAM_SIZE,
				((parser_mad->mad->u32ParserBufSize[u16ParserID]) >> Bitshift4));
		}
		MAD_RIU_WRITE_WORD(REG_PASD_DMA_DRAM_OVERRUN_THRESHOLD,
			((parser_mad->mad->u32ParserBufSize[u16ParserID]) >> 1));
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_MIU_BURST_LENGTH, BusrtlengthMask,
			_BIT_1_ | _BIT_0_);

		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_2_, _BIT_2_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_14_, _BIT_14_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_14_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, 0x0001, 0x0001);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_10_, _BIT_10_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL_1, _BIT_15_ | _BIT_9_,
			_BIT_15_ | _BIT_9_);

		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV) {
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND, _BIT_0_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND_1, _BIT_7_ | _BIT_2_, _BIT_7_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_0_ , _BIT_0_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND, _BIT_1_, _BIT_1_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND, _BIT_1_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND_1, _BIT_0_, _BIT_0_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND_1, _BIT_0_, 0x0000);
		} else {
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND, _BIT_0_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND_1, _BIT_7_, 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_0_ , 0x0000);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND, _BIT_0_, _BIT_0_);
			udelay(time_15);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL_2ND, _BIT_0_, 0x0000);
		}

		MAD_RIU_MASK_WRITE_WORD(REG_PAS_CD_PTS_BYTE_CTRL, _BIT_3_, _BIT_3_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_CD_PTS_BYTE_CTRL, _BIT_3_, 0x0000);

		MAD_RIU_MASK_WRITE_WORD(REG_MAD_MCU_CTRL, BitMask8,
			_BIT_3_ | _BIT_2_ | _BIT_1_ | _BIT_0_);
		MAD_RIU_WRITE_WORD(REG_MAD_CTRL2, _BIT_15_ | _BIT_8_ | _BIT_7_);

		MAD_RIU_WRITE_WORD(REG_PASD_STREAM_ID1, StreamID1);
		MAD_RIU_WRITE_WORD(REG_PASD_STREAM_ID2, StreamID2);
		if (secure_flag == 1) {
			struct _ST_AUDIO_SECURE_INFO param;
			int ret = 0;

			param.u8SvpEnableFlag = 1;
			param.u32pipelineID = parser_mad->mad->u32PipeId[u16ParserID];
			param.u16ParserId = u16ParserID;
			param.u8Version = 0x1;
			ret = mad_parser_tee_setmode(u16ParserID, &param);
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s =[%d]\n", __func__, ret);
		}
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_EXTRA_HDR_CTRL, _BIT_14_ | _BIT_13_,
			_BIT_14_ | _BIT_13_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, ParserControlMask,
			_BIT_14_ | _BIT_9_ | _BIT_4_);

		MAD_RIU_WRITE_WORD(REG_MAD_CTRL2, _BIT_15_ | _BIT_8_);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_CTRL2, 0x0001, 0x00001);
		MAD_RIU_MASK_WRITE_WORD(REG_MAD_CTRL2, 0x0001, 0x00000);

		if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV){
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_EXTRA_HDR_CTRL, _BIT_14_ | _BIT_13_, 0x0000);

			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_15_| _BIT_14_| _BIT_10_| _BIT_9_ , _BIT_15_| _BIT_9_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_4_ , _BIT_4_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_7_ | _BIT_4_ | _BIT_1_ , _BIT_1_);
		}else{
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_4_ , _BIT_4_);
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_4_ | _BIT_3_ | _BIT_2_, 0x0000);
        }

		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_12_, _BIT_12_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_12_, 0);

		parser_mad->mad->reg_pas_rdata_sel_mask[mad_3] = ParserRdataSelMask1;
		parser_mad->mad->reg_pas_rdata_sel_a2d_str_type[mad_3] = REG_PASD_SELECT_STR_TYPE;

		mdelay(1);
		//Start parser
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_7_, 0);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_2_, 0);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_CD_PTS_BYTE_CTRL, _BIT_1_, 0);
		break;
	default:
		drv_ret = PAS_RESULT_FAIL;
		break;
	}
	if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV){
		create_param.u64SecureEsStartAddr = parser_mad->mad->u64TLVBufAddr[u16ParserID];
		create_param.u64SecureEsEndAddr = parser_mad->mad->u64TLVBufAddr[u16ParserID] + (u64)(parser_mad->mad->u32TLVBufSize[u16ParserID]);
		create_param.u64NonSecureEsStartAddr = parser_mad->mad->u64ParserBufAddr[u16ParserID];
		create_param.u64NonSecureEsEndAddr = parser_mad->mad->u64ParserBufAddr[u16ParserID] + (u64)(parser_mad->mad->u32ParserBufSize[u16ParserID]);
		create_param.u16ParserId = u16ParserID;
		mad_parser_tee_create(u16ParserID, &create_param);
	}
	_DRV_MAD_LockCreate(u16ParserID);
	return drv_ret;
}

parser_drv_result _mad_stop(int idx)
{
	parser_drv_result drv_ret = PAS_RESULT_OK;

	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s =[%d]\n", __func__, idx);

	switch (idx) {
	case mad_0:
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_7_, _BIT_7_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_2_, _BIT_2_);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_AB_PTS_BYTE_CTRL, _BIT_2_, _BIT_2_);

		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_5_, _BIT_5_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_5_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_0_, 0);
		break;
	case mad_1:
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_7_, _BIT_7_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_2_, _BIT_2_);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_AB_PTS_BYTE_CTRL, _BIT_3_, _BIT_3_);

		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_5_, _BIT_5_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_5_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_0_, 0);
		break;
	case mad_2:
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_7_, _BIT_7_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_2_, _BIT_2_);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_CD_PTS_BYTE_CTRL, _BIT_2_, _BIT_2_);

		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_5_, _BIT_5_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_5_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_0_, 0);
		break;
	case mad_3:
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_7_, _BIT_7_);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_2_, _BIT_2_);
		MAD_RIU_MASK_WRITE_WORD(REG_PAS_CD_PTS_BYTE_CTRL, _BIT_3_, _BIT_3_);

		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_5_, _BIT_5_);
		mdelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_5_, 0x0000);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_0_, 0);
		break;
	default:
		drv_ret = PAS_RESULT_FAIL;
		break;
	}

	return drv_ret;
}

void mad_parser_start(u16 parser_id)
{
	switch (parser_id) {
	case mad_0:
		if ((MAD_RIU_READ_WORD(REG_PASA_CTRL))&ParserStopMask)
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_7_, 0);
		break;
	case mad_1:
		if ((MAD_RIU_READ_WORD(REG_PASB_CTRL))&ParserStopMask)
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_7_, 0);
		break;
	case mad_2:
		if ((MAD_RIU_READ_WORD(REG_PASC_CTRL))&ParserStopMask)
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_7_, 0);
		break;
	case mad_3:
		if ((MAD_RIU_READ_WORD(REG_PASD_CTRL))&ParserStopMask)
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_7_, 0);
		break;
	default:
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
		"%s wrong parser id\n", __func__);
		break;
	}
	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s %d\n", __func__, parser_id);
}

void mad_parser_stop(u16 parser_id)
{
	switch (parser_id) {
	case mad_0:
		if ((MAD_RIU_READ_WORD(REG_PASA_CTRL)&ParserStopMask) != ParserStopMask)
			MAD_RIU_MASK_WRITE_WORD(REG_PASA_CTRL, _BIT_7_, _BIT_7_);
		break;
	case mad_1:
		if ((MAD_RIU_READ_WORD(REG_PASB_CTRL)&ParserStopMask) != ParserStopMask)
			MAD_RIU_MASK_WRITE_WORD(REG_PASB_CTRL, _BIT_7_, _BIT_7_);
		break;
	case mad_2:
		if ((MAD_RIU_READ_WORD(REG_PASC_CTRL)&ParserStopMask) != ParserStopMask)
			MAD_RIU_MASK_WRITE_WORD(REG_PASC_CTRL, _BIT_7_, _BIT_7_);
		break;
	case mad_3:
		if ((MAD_RIU_READ_WORD(REG_PASD_CTRL)&ParserStopMask) != ParserStopMask)
			MAD_RIU_MASK_WRITE_WORD(REG_PASD_CTRL, _BIT_7_, _BIT_7_);
		break;
	default:
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
		"%s wrong parser id\n", __func__);
		break;
	}
	iBufferFullCnt[parser_id]++;
	PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "%s %d\n", __func__, parser_id);
}

void esbuffer_full_check(u16 parser_id, u32 es_memcnt)
{
	u32 es_level_threshold = (parser_mad->mad->u32ParserBufSize[parser_id]>>1);

	if (es_memcnt > es_level_threshold) {
		mad_parser_stop(parser_id);
		parser_mad->mad->u8BufOverflow[parser_id] = 1;
	} else {
		mad_parser_start(parser_id);
		parser_mad->mad->u8BufOverflow[parser_id] = 0;
	}
}

#define LOOPMSG_CNT 20
static int _MDrv_MAD_TLV_BufHandler(u16 *data)
{
	u16 parser_id = *data;
	u32 es_memcnt = 0, esbytecnt = 0, es_memcnt_tmp = 0;
	struct mtk_bc_ctx *buf_ctx = parser_mad->mad->buf_ctx[parser_id];
	unsigned long flags = 0;
	u16 tlv_wridx, tlv_rdidx;
	u16 ret;
	struct ST_AUDIO_PARSER_FRAMING_PARAM param;
	int loopcnt = 0;
	int iWaitBufCnt = 0;
	int iWaitDataCnt = 0;
	int iFrameFailCnt = 0;
	parser_mad->mad->u32writePreEScount[parser_id] = 0;

	set_freezable();

	while (1) {
		if (kthread_should_stop()) {
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s stop TLV parser_id %d\n", __func__, parser_id);
			_DRV_MAD_Lock(parser_id);
			parser_mad->mad->u32thread_stop[parser_id] = 1;
			_DRV_MAD_UnLock(parser_id);
			break;
		}
		try_to_freeze();
		loopcnt++;
		if (loopcnt % LOOPMSG_CNT == 0) {
			if ((iWaitBufCnt != 0) || (iWaitDataCnt != 0) || (iFrameFailCnt != 0))
			{
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
					"[%s] %d PAS(%d) cnt %d  es %d data %d\n", __func__, __LINE__,
					parser_id, loopcnt, iWaitBufCnt, iWaitDataCnt);
				iWaitBufCnt = 0;
				iWaitDataCnt = 0;
				iFrameFailCnt = 0;
			}
		}

		if (parser_mad->mad->dvb2_buf[parser_id] == NULL) {
			struct dma_buf *db = NULL;
			struct platform_device *pdev =	parser_mad->pdev;
			struct device *dev = &pdev->dev;
			struct dvb2_buffer *ret_buf = NULL;
			struct dvb2_vb2_ctx *vb2_ctx = parser_mad->mad->ctx[parser_id];
			if (vb2_ctx == NULL) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
					"dma_buf_map_attachment vb2_ctx is NULL\n");
				usleep_range(time_500, time_1000);
				continue;
			}

			if (!dvb2_vb2_is_streaming(vb2_ctx)) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "[%d] _MDrv_MAD stream off\n", parser_id);
				continue;
			}

			spin_lock_irqsave(&vb2_ctx->slock, flags);
			if (list_empty(&vb2_ctx->dvb_q)) {
				spin_unlock_irqrestore(&vb2_ctx->slock, flags);
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"list_empty is NULL\n");
				iWaitBufCnt++;
				usleep_range(time_500, time_1000);
				continue;
			}

			ret_buf = list_entry(vb2_ctx->dvb_q.next, struct dvb2_buffer, list);
			spin_unlock_irqrestore(&vb2_ctx->slock, flags);
			if (ret_buf != NULL) {
				db = ret_buf->vb.planes[0].dbuf;
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"dma_buf_map_attachment ret_buf is OK\n");
			} else {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"dma_buf_map_attachment ret_buf is NULL\n");
				usleep_range(time_500, time_1000);
				continue;
			}

			if (db == NULL) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
					"dma_buf_map_attachment db is NULL\n");
				usleep_range(time_500, time_1000);
				continue;
			}

			if (dev == NULL) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
					"dma_buf_map_attachment dev is NULL\n");
				usleep_range(time_500, time_1000);
				continue;
			}

			parser_mad->mad->dvb2_buf[parser_id] = ret_buf;
			parser_mad->mad->ctx[parser_id] = vb2_ctx;
			parser_mad->mad->ctx[parser_id]->buf = ret_buf;
			parser_mad->mad->s32PasOutputBufFd[parser_id] =
				ret_buf->vb.planes[0].m.fd;
			parser_mad->mad->buf_ctx[parser_id] = buf_ctx;
		}

		_DRV_MAD_Lock(parser_id);
		switch (parser_id) {
			case mad_0:
				MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
				udelay(time_20);
				es_memcnt = (MAD_RIU_READ_WORD(REG_PASA_DMA_DRAM_LEVEL_CNT) << Bitshift4);
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s  inputES, esmem:%u %u\n", __func__, es_memcnt,
					parser_mad->mad->u32writePreEScount[parser_id]);
				MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_5_, 0x0000);
				break;
			case mad_1:
				MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
				udelay(time_20);
				es_memcnt = (MAD_RIU_READ_WORD(REG_PASB_DMA_DRAM_LEVEL_CNT) << Bitshift4);
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s  inputES, esmem:%u %u\n", __func__, es_memcnt,
					parser_mad->mad->u32writePreEScount[parser_id]);
				MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_5_, 0x0000);
				break;
			case mad_2:
				MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
				udelay(time_20);
				es_memcnt = (MAD_RIU_READ_WORD(REG_PASC_DMA_DRAM_LEVEL_CNT) << Bitshift4);
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s  inputES, esmem:%u %u\n", __func__, es_memcnt,
					parser_mad->mad->u32writePreEScount[parser_id]);
				MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_5_, 0x0000);
				break;
			case mad_3:
				MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
				udelay(time_20);
				es_memcnt = (MAD_RIU_READ_WORD(REG_PASD_DMA_DRAM_LEVEL_CNT) << Bitshift4);
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s  inputES, esmem:%u %u\n", __func__, es_memcnt,
					parser_mad->mad->u32writePreEScount[parser_id]);
				MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_5_, 0x0000);
				break;
			default:
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
					"%s  error parser id\n", __func__);
				break;
		}
		es_memcnt_tmp = parser_mad->mad->u32writePreEScount[parser_id];
		_DRV_MAD_UnLock(parser_id);

		esbuffer_full_check(parser_id, es_memcnt);
		if (es_memcnt < es_memcnt_tmp) {
			usleep_range(time_500, time_1000);
			continue;
		} else
			es_memcnt = es_memcnt - es_memcnt_tmp;

		tlv_wridx = parser_mad->mad->tlv_wridx_s[parser_id];
		tlv_rdidx = parser_mad->mad->tlv_rdidx_s[parser_id];
		if (tlv_wridx - tlv_rdidx != 0) {
			tlv_wridx = tlv_rdidx+1;
			if (tlv_wridx >= MAX_TLV_INFO_NUM)
				tlv_wridx = 0;
		}
		if (tlv_wridx != tlv_rdidx) {
			//invoke command to TEE
			memset(&param, 0, sizeof(param));
			param.u32SequenceLng =
				parser_mad->mad->stTlvInfoTable[parser_id].u32lng[tlv_wridx];
			param.u32SequenceNum =
				parser_mad->mad->stTlvInfoTable[parser_id].u32seq[tlv_wridx];
			param.u32InSecureEsDataOffset = parser_mad->mad->u32secure_es_wrptr[parser_id];
			param.u32InSecureEsDataSize = es_memcnt;
			param.u32InNonSecureEsDataOffset = parser_mad->mad->u32es_wrptr[parser_id];
			param.u32OutSecureEsDataOffset = 0;
			param.u32OutNonSecureEsDataOffset = 0;
			param.u32OutNonSecureEsDataSize = 0;
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "send TLV[%d][%d][%d][%d][%d][%d] to TEE \n", parser_id, param.u32SequenceLng, param.u32SequenceNum,
				param.u32InSecureEsDataOffset, param.u32InSecureEsDataSize, param.u32InNonSecureEsDataOffset);
			ret = mad_parser_tee_framing(parser_id, &param);
			if (ret != 0)
				iFrameFailCnt++;

			es_memcnt = param.u32OutNonSecureEsDataSize;
			esbytecnt =
				parser_mad->mad->stTlvInfoTable[parser_id].u32esbytecnt[tlv_wridx];

			//wait TEE callback
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
				"get TLV[%d]packet[%d]ES[%d][%d][%d][%d] from TEE\n",
				parser_id, tlv_wridx, es_memcnt,
				param.u32OutNonSecureEsDataOffset, param.u32OutSecureEsDataOffset, esbytecnt);
			if (es_memcnt > 0) {
				struct dmx2_ts_audio_metadata meta;
				struct dvb2_vb2_ctx *ctx = parser_mad->mad->ctx[parser_id];

				parser_mad->mad->tlv_rdidx_s[parser_id]++;
				if (parser_mad->mad->tlv_rdidx_s[parser_id] >= MAX_TLV_INFO_NUM)
					parser_mad->mad->tlv_rdidx_s[parser_id] = 0;

				if (!dvb2_vb2_is_streaming(ctx)) {
					PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "[%d] _MDrv_MAD stream off\n", parser_id);
					continue;
				}
				meta.data_offset = parser_mad->mad->u32es_wrptr[parser_id];
				meta.reserved[0] =  es_memcnt;
				meta.reserved[reg_2] = parser_mad->mad->u8BufOverflow[parser_id];
				meta.pts_present = 1;
				meta.timestamp =
				parser_mad->mad->stTlvInfoTable[parser_id].u32seq[tlv_wridx];
				ret = mtk_bc_metabuf_queue(buf_ctx, &meta);
				//parser_mad->mad->u32es_wrptr[parser_id] += es_memcnt;
				parser_mad->mad->u32secure_es_wrptr[parser_id] = param.u32OutSecureEsDataOffset;
				parser_mad->mad->u32es_wrptr[parser_id] = param.u32OutNonSecureEsDataOffset;
				_DRV_MAD_Lock(parser_id);

				parser_mad->mad->u32writePreEScount[parser_id] += meta.reserved[0];

				_DRV_MAD_UnLock(parser_id);

				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s report done, es:%u, flag:%d, seq:%llu, wrptr:%u, ovr:%d, %u\n",
					__func__, ((meta.reserved[0])), meta.pts_present,
					meta.timestamp, meta.data_offset, meta.reserved[reg_2],
					parser_mad->mad->u32writePreEScount[parser_id]);
			} else {
				iWaitDataCnt++;
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s valid meta\n", __func__);
			}
		}
		usleep_range(time_9000, time_10000);
	}
	return 1;
}

static int _MDrv_MAD_BufHandler(u16 *data)
{
	u16 parser_id = *data;
	u32 es_memcnt = 0, es_memcnt_tmp = 0;
	struct mtk_bc_ctx *buf_ctx = parser_mad->mad->buf_ctx[parser_id];
	unsigned long flags = 0;
	u16 pts_wridx, pts_rdidx;
	parser_drv_result drv_ret = 0;
	int loopcnt = 0;
	int iWaitBufCnt = 0;
	int iWaitDataCnt = 0;
	parser_mad->mad->u32writePreEScount[parser_id] = 0;

	set_freezable();
	while (1) {
		if (kthread_should_stop()) {
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s stop parser_id %d\n", __func__, parser_id);
			_DRV_MAD_Lock(parser_id);
			parser_mad->mad->u32thread_stop[parser_id] = 1;
			_DRV_MAD_UnLock(parser_id);
			break;
		}
		try_to_freeze();
		loopcnt++;
		if (loopcnt % LOOPMSG_CNT == 0) {
			if ((iWaitBufCnt != 0) || (iWaitDataCnt != 0) ||
			(iBufferFullCnt[parser_id] != 0))
			{
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
					"[%s] %d PAS(%d) cnt %d  es %d data %d full %d\n",
					__func__, __LINE__,	parser_id, loopcnt,
					iWaitBufCnt, iWaitDataCnt, iBufferFullCnt[parser_id]);
				iWaitBufCnt = 0;
				iWaitDataCnt = 0;
				iBufferFullCnt[parser_id] = 0;
			}
		}

		_DRV_MAD_Lock(parser_id);
		switch (parser_id) {
			case mad_0:
				MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
				udelay(sleeptime);
				es_memcnt = (MAD_RIU_READ_WORD(REG_PASA_DMA_DRAM_LEVEL_CNT) << Bitshift4);
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s  inputES, esmem:%u %u %u %lld %lld\n", __func__,
					es_memcnt,
					parser_mad->mad->u32writePreEScount[parser_id],
					MAD_RIU_READ_WORD(REG_PASA_DMA_DRAM_WRITE_POINT),
					parser_mad->mad->u64writeEScount[parser_id],
					parser_mad->mad->u64readEScount[parser_id]);
				MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_5_, 0x0000);
				break;
			case mad_1:
				MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
				udelay(sleeptime);
				es_memcnt = (MAD_RIU_READ_WORD(REG_PASB_DMA_DRAM_LEVEL_CNT) << Bitshift4);
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s  inputES, esmem:%u %u %u %lld %lld\n", __func__,
					es_memcnt,
					parser_mad->mad->u32writePreEScount[parser_id],
					MAD_RIU_READ_WORD(REG_PASB_DMA_DRAM_WRITE_POINT),
					parser_mad->mad->u64writeEScount[parser_id],
					parser_mad->mad->u64readEScount[parser_id]);
				MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_5_, 0x0000);
				break;
			case mad_2:
				MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
				udelay(sleeptime);
				es_memcnt = (MAD_RIU_READ_WORD(REG_PASC_DMA_DRAM_LEVEL_CNT) << Bitshift4);
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s  inputES, esmem:%u %u %u %lld %lld\n", __func__,
					es_memcnt,
					parser_mad->mad->u32writePreEScount[parser_id],
					MAD_RIU_READ_WORD(REG_PASC_DMA_DRAM_WRITE_POINT),
					parser_mad->mad->u64writeEScount[parser_id],
					parser_mad->mad->u64readEScount[parser_id]);
				MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_5_, 0x0000);
				break;
			case mad_3:
				MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
				udelay(sleeptime);
				es_memcnt = (MAD_RIU_READ_WORD(REG_PASD_DMA_DRAM_LEVEL_CNT) << Bitshift4);
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s  inputES, esmem:%u %u %u %lld %lld\n", __func__,
					es_memcnt,
					parser_mad->mad->u32writePreEScount[parser_id],
					MAD_RIU_READ_WORD(REG_PASD_DMA_DRAM_WRITE_POINT),
					parser_mad->mad->u64writeEScount[parser_id],
					parser_mad->mad->u64readEScount[parser_id]);
				MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_5_, 0x0000);
				break;
			default:
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
					"%s  error parser id\n", __func__);
				break;
		}
		es_memcnt_tmp = parser_mad->mad->u32writePreEScount[parser_id];
		_DRV_MAD_UnLock(parser_id);

		esbuffer_full_check(parser_id, es_memcnt);

		if (es_memcnt < es_memcnt_tmp) {
			usleep_range(time_500, time_1000);
			continue;
		} else
			es_memcnt = es_memcnt - es_memcnt_tmp;

		if (parser_mad->mad->dvb2_buf[parser_id] == NULL) {
			struct dma_buf *db = NULL;
			struct platform_device *pdev =	parser_mad->pdev;
			struct device *dev = &pdev->dev;
			struct dvb2_buffer *ret_buf = NULL;
			struct dvb2_vb2_ctx *vb2_ctx = parser_mad->mad->ctx[parser_id];

			if (vb2_ctx == NULL) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
					"dma_buf_map_attachment vb2_ctx is NULL\n");
				usleep_range(time_500, time_1000);
				continue;
			}

			if (_MDrv_MAD_Vb2Valid(parser_id) == false) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "[%d] _MDrv_MAD stream off\n", parser_id);
				drv_ret = _mad_stop(parser_id);
				if (drv_ret != 0)
					PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "[%d] MAD stream off stop fail\n", parser_id);
				usleep_range(time_500, time_1000);
				continue;
			}

			spin_lock_irqsave(&vb2_ctx->slock, flags);
			if (list_empty(&vb2_ctx->dvb_q)) {
				spin_unlock_irqrestore(&vb2_ctx->slock, flags);
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"list_empty is NULL\n");
				iWaitBufCnt++;
				usleep_range(time_5000, time_6000);
				continue;
			}

			ret_buf = list_entry(vb2_ctx->dvb_q.next, struct dvb2_buffer, list);
			spin_unlock_irqrestore(&vb2_ctx->slock, flags);
			if (ret_buf != NULL) {
				db = ret_buf->vb.planes[0].dbuf;
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"dma_buf_map_attachment ret_buf is OK\n");
			} else {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"dma_buf_map_attachment ret_buf is NULL\n");
				usleep_range(time_500, time_1000);
				continue;
			}

			if (db == NULL) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
					"dma_buf_map_attachment db is NULL\n");
				usleep_range(time_500, time_1000);
				continue;
			}

			if (dev == NULL) {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
				    "dma_buf_map_attachment dev is NULL\n");
				usleep_range(time_500, time_1000);
				continue;
			}

			parser_mad->mad->dvb2_buf[parser_id] = ret_buf;
			parser_mad->mad->ctx[parser_id] = vb2_ctx;
			parser_mad->mad->ctx[parser_id]->buf = ret_buf;
			parser_mad->mad->s32PasOutputBufFd[parser_id] =
			    ret_buf->vb.planes[0].m.fd;
			parser_mad->mad->buf_ctx[parser_id] = buf_ctx;
		}

		if (es_memcnt > 0) {
			struct dmx2_ts_audio_metadata meta;
			int ret;
			struct dvb2_vb2_ctx *ctx = parser_mad->mad->ctx[parser_id];
			meta.timestamp = 0;

			if ((audio_parser_get_entry(parser_id, &meta, es_memcnt) == 1) &&
				(buf_ctx != NULL)) {
				if (!dvb2_vb2_is_streaming(ctx)) {
					PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "[%d] _MDrv_MAD stream off\n", parser_id);
					continue;
				}
				ret = mtk_bc_metabuf_queue(buf_ctx, &meta);

				parser_mad->mad->u64writeEScount[parser_id] +=
					(meta.reserved[0]);
				_DRV_MAD_Lock(parser_id);
				parser_mad->mad->u32writePreEScount[parser_id] +=
					(meta.reserved[0]);
				_DRV_MAD_UnLock(parser_id);

				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s report done[%d], es:%u, flag:%d, pts:%llu, wrptr:%u, wrcnt:0x%llx, ovr:%d, %d, %u\n",
					__func__, parser_id, (meta.reserved[0]),
					meta.pts_present, meta.timestamp, meta.data_offset,
					parser_mad->mad->u64writeEScount[parser_id],
					meta.reserved[reg_2], ret,
					parser_mad->mad->u32writePreEScount[parser_id]);
			} else {
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
					"%s valid meta\n", __func__);
			}
		} else {
				iWaitDataCnt++;
				PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
				"%s report done(No ES)\n", __func__);
		}

		pts_wridx = parser_mad->mad->pts_wridx[parser_id];
		pts_rdidx = parser_mad->mad->pts_rdidx[parser_id];
		if ((pts_wridx == pts_rdidx) || (es_memcnt == 0))
			usleep_range(time_9000, time_10000);
		else
			usleep_range(time_2000, time_3000);
	}
	return 1;
}

int mdrv_pes_parser_mad_init(u16 u16ParserID, struct platform_device *pdev,
	struct mtk_dmx2dev *dmxdev, struct dvb2_vb2_ctx *vb2_ctx, struct mtk_bc_ctx *buf_ctx,
	enum dmx2_main_filter_type type, struct dmx2_filter *filter)
{
	struct dma_buf_attachment *buf_att;
	struct sg_table *sgt;
	struct dma_buf *db = NULL;
	struct device *dev = &pdev->dev;
	struct dvb2_buffer *ret_buf = NULL;
	unsigned long flags = 0;
	u16 bit = 1;

	bit <<= u16ParserID;

	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s[%d][%d] version 0x521900\n", __func__, u16ParserID, type);

	if (u16ParserID >= MAX_MAD_NUM) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "id: %d\n", u16ParserID);
		return -1;
	}
	if (!parser_mad) {
		parser_mad = vmalloc(sizeof(struct mdrv_pes_parser));

		if (parser_mad == NULL) {
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "parser_mad is NULL\n");
			return -1;
		}
		memset((u8 *)parser_mad, 0, sizeof(struct mdrv_pes_parser));
	}
	parser_mad->pdev = pdev;

	// init mad handler
	parser_mad->mad_num = MAX_MAD_NUM;

	if (!parser_mad->mad) {
		parser_mad->mad = vmalloc(sizeof(struct pes_parser_handler) * parser_mad->mad_num);

		if (parser_mad->mad == NULL) {
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "parser_mad->mad is NULL\n");
			return -1;
		}
		memset((u8 *)parser_mad->mad, 0,
			(sizeof(struct pes_parser_handler) * parser_mad->mad_num));
	}

	if (parser_mad->mad->init_flag[u16ParserID] == 1) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "mad already init[%d]\n", u16ParserID);
		return 0;
	}

	if (vb2_ctx == NULL) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "dma_buf_map_attachment vb2_ctx is NULL\n");
		return 0;
	}

	spin_lock_irqsave(&vb2_ctx->slock, flags);
	if (list_empty(&vb2_ctx->dvb_q)) {
		spin_unlock_irqrestore(&vb2_ctx->slock, flags);
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "dma_buf_map_attachment list buffer is NULL\n");
		return 0;
	}

	ret_buf = list_entry(vb2_ctx->dvb_q.next, struct dvb2_buffer, list);
	spin_unlock_irqrestore(&vb2_ctx->slock, flags);
	if (ret_buf != NULL) {
		parser_mad->mad->dvb2_buf[u16ParserID] = ret_buf;
		db = ret_buf->vb.planes[0].dbuf;
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "dma_buf_map_attachment ret_buf is OK\n");
	}else {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "list_entry is NULL\n");
		return 0;
	}

	if (db == NULL) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "dma_buf_map_attachment db is NULL\n");
		return 0;
	}

	if (dev == NULL) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "dma_buf_map_attachment dev is NULL\n");
		return 0;
	}

	buf_att = dma_buf_attach(db, &pdev->dev);
	sgt = dma_buf_map_attachment(buf_att, DMA_BIDIRECTIONAL);

	if (!sgt) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "dma_buf_map_attachment sgt is NULL\n");
		return 0;
	}

	parser_mad->mad->u64ParserBufAddr[u16ParserID]  = sg_dma_address(sgt->sgl);
	parser_mad->mad->u32ParserBufSize[u16ParserID]  = vb2_ctx->buf_siz;
	parser_mad->mad->ctx[u16ParserID] = vb2_ctx;
	parser_mad->mad->ctx[u16ParserID]->buf = ret_buf;
	parser_mad->mad->s32PasOutputBufFd[u16ParserID] = ret_buf->vb.planes[0].m.fd;
	parser_mad->mad->buf_ctx[u16ParserID] = buf_ctx;
	parser_mad->mad->filter_type[u16ParserID] = type;
	parser_mad->mad->filter[u16ParserID] = filter;
	parser_mad->mad->prev_meta[u16ParserID].ad.fade = 0;
	parser_mad->mad->prev_meta[u16ParserID].ad.pan = 0;
	parser_mad->mad->prev_meta[u16ParserID].ad.gain_center = 0;
	parser_mad->mad->prev_meta[u16ParserID].ad.gain_front = 0;
	parser_mad->mad->prev_meta[u16ParserID].ad.gain_surround = 0;
	parser_mad->mad->prev_meta[u16ParserID].ad_present = 0;
	parser_mad->mad->curr_meta[u16ParserID].ad.fade = 0;
	parser_mad->mad->curr_meta[u16ParserID].ad.pan = 0;
	parser_mad->mad->curr_meta[u16ParserID].ad.gain_center = 0;
	parser_mad->mad->curr_meta[u16ParserID].ad.gain_front = 0;
	parser_mad->mad->curr_meta[u16ParserID].ad.gain_surround = 0;
	parser_mad->mad->u64writeEScount[u16ParserID] = 0;
	parser_mad->mad->u64readEScount[u16ParserID] = 0;
	parser_mad->mad->u8BufOverflow[u16ParserID] = 0;
	parser_mad->mad->es_accum[u16ParserID] = 0;

	dma_buf_unmap_attachment(buf_att, sgt, DMA_BIDIRECTIONAL);
	dma_buf_detach(db, buf_att);

	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "IOMMU addr = 0x%llx size = 0x%08x\n",
		parser_mad->mad->u64ParserBufAddr[u16ParserID],
		parser_mad->mad->u32ParserBufSize[u16ParserID]);
	if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV){
		if (mtk_dmx_rm_get_buf(&dmxdev->rm, MMAP_BUF_TYPE_MAD, parser_mad->mad->u32ParserBufSize[u16ParserID], &parser_mad->mad->mad_buffer[u16ParserID]) < 0) {
				MTK_DMX_ERR("get FW buf fail\n");
				return 0;
		}
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "IOMMU PA = 0x%llx\n",
		parser_mad->mad->mad_buffer[u16ParserID].paddr);
		parser_mad->mad->u64TLVBufAddr[u16ParserID] = parser_mad->mad->mad_buffer[u16ParserID].paddr;
		parser_mad->mad->u32TLVBufSize[u16ParserID] = parser_mad->mad->u32ParserBufSize[u16ParserID];
	}

	MAD_RIU_MASK_WRITE_WORD(REG_PAS_PTS_INT_CTRL, bit, 0);
	_mad_start(u16ParserID);

	mdrv_pes_parser_mad_create_thread(u16ParserID);

	parser_mad->mad->init_flag[u16ParserID] = 1;
	MAD_RIU_MASK_WRITE_WORD(REG_PAS_PTS_INT_CTRL, bit, bit);

	return 1;
}

static int _MDrv_MAD_BufHandler0(void *data)
{
	u16 parser_id = 0;

	if (data != NULL)
		parser_id = (*(u16 *)(data));

	if (parser_id >= MAX_MAD_NUM)
		parser_id = mad_0;
	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s parser_id %d\n", __func__, parser_id);
	if (parser_mad->mad->filter_type[parser_id] == DMX2_FILTER_TYPE_TLV)
		return _MDrv_MAD_TLV_BufHandler(&parser_id);
	else
	return _MDrv_MAD_BufHandler(&parser_id);
}

static int _MDrv_MAD_BufHandler1(void *data)
{
	u16 parser_id = 0;

	if (data != NULL)
		parser_id = (*(u16 *)(data));

	if (parser_id >= MAX_MAD_NUM)
		parser_id = mad_1;
	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s parser_id %d\n", __func__, parser_id);
	if (parser_mad->mad->filter_type[parser_id] == DMX2_FILTER_TYPE_TLV)
		return _MDrv_MAD_TLV_BufHandler(&parser_id);
	else
	return _MDrv_MAD_BufHandler(&parser_id);
}

static int _MDrv_MAD_BufHandler2(void *data)
{
	u16 parser_id = 0;

	if (data != NULL)
		parser_id = (*(u16 *)(data));

	if (parser_id >= MAX_MAD_NUM)
		parser_id = mad_2;
	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s parser_id %d\n", __func__, parser_id);
	if (parser_mad->mad->filter_type[parser_id] == DMX2_FILTER_TYPE_TLV)
		return _MDrv_MAD_TLV_BufHandler(&parser_id);
	else
	return _MDrv_MAD_BufHandler(&parser_id);
}

static int _MDrv_MAD_BufHandler3(void *data)
{
	u16 parser_id = 0;

	if (data != NULL)
		parser_id = (*(u16 *)(data));

	if (parser_id >= MAX_MAD_NUM)
		parser_id = mad_3;
	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s parser_id %d\n", __func__, parser_id);
	if (parser_mad->mad->filter_type[parser_id] == DMX2_FILTER_TYPE_TLV)
		return _MDrv_MAD_TLV_BufHandler(&parser_id);
	else
	return _MDrv_MAD_BufHandler(&parser_id);
}

void mdrv_pes_parser_mad_create_thread(u16 u16ParserID)
{
	pTaskArg[u16ParserID] = (u16*)kzalloc(sizeof(u16), GFP_KERNEL);
	if (pTaskArg[u16ParserID] == NULL) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "kthread_alloc arg fail, ID %d\n", u16ParserID);
	}
	*pTaskArg[u16ParserID] = u16ParserID;

	if (u16ParserID == mad_0)
		pTask[u16ParserID] = kthread_create(_MDrv_MAD_BufHandler0, (void *)(pTaskArg[u16ParserID]),
			"mtkmad0_buf_handler");
	else if (u16ParserID == mad_1)
		pTask[u16ParserID] = kthread_create(_MDrv_MAD_BufHandler1, (void *)(pTaskArg[u16ParserID]),
			"mtkmad1_buf_handler");
	else if (u16ParserID == mad_2)
		pTask[u16ParserID] = kthread_create(_MDrv_MAD_BufHandler2, (void *)(pTaskArg[u16ParserID]),
			"mtkmad2_buf_handler");
	else if (u16ParserID == mad_3)
		pTask[u16ParserID] = kthread_create(_MDrv_MAD_BufHandler3, (void *)(pTaskArg[u16ParserID]),
			"mtkmad3_buf_handler");
	else {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "creat thread id[%d] is out of range\n",
			u16ParserID);
		return;
	}

	if (IS_ERR(pTask[u16ParserID])) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "creat thread id[%d] fail\n",
			u16ParserID);
	} else {
		wake_up_process(pTask[u16ParserID]);
	}
}

int audio_parser_set_control(u16 parser_id, enum audio_parser_control_command cmd,
	struct audio_parser_ctrl *p_ctrl)
{
	if (p_ctrl == NULL) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "p_ctrl is NULL\n");
		return 0;
	}

	if (parser_mad == NULL) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "parser_mad is NULL\n");
		return 0;
	}

	if (parser_id >= MAX_MAD_NUM) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "id: %d\n", parser_id);
		return 0;
	}

	if (parser_mad->mad == NULL) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "parser_mad->mad is NULL\n");
		return -1;
	}

	if (parser_mad->mad->init_flag[parser_id] == 0) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "mad not init yet[%d]\n", parser_id);
		return 0;
	}

	switch (cmd) {
	case APAS_CMD_SET_SECURE:
	{
		int pipeline_id = 0;

		pipeline_id = p_ctrl->value;

		if (pipeline_id == 0)
			secure_flag = 0;
		else
			secure_flag = 1;

		parser_mad->mad->u32PipeId[parser_id] = pipeline_id;
	}
		break;
	default:
		break;
	}

	PAS_DEBUG_LOG(PAS_LOG_LEVEL_DEBUG, "ok\n");
	return 1;
}
int mdrv_pes_parser_mad_exit(u16 u16ParserID, struct platform_device *pdev, struct mtk_dmx2dev *dmxdev)
{
	u16 sleep_count = 0;
	u32 stop_command = 0;

	if (u16ParserID >= MAX_MAD_NUM) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "id: %d\n", u16ParserID);
		return -1;
	}

	if (parser_mad) {
		// free mad handler
		if (parser_mad->mad) {
			if (parser_mad->mad->init_flag[u16ParserID] == 0)
				return 1;
			_mad_stop(u16ParserID);
			kthread_stop(pTask[u16ParserID]);
			_DRV_MAD_Lock(u16ParserID);
			stop_command = parser_mad->mad->u32thread_stop[u16ParserID];
			_DRV_MAD_UnLock(u16ParserID);
			while(stop_command == 0) {
				usleep_range(time_9000, time_10000);
				sleep_count ++;
				_DRV_MAD_Lock(u16ParserID);
				stop_command = parser_mad->mad->u32thread_stop[u16ParserID];
				_DRV_MAD_UnLock(u16ParserID);
				if (sleep_count >= time_20) {
					PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "%s stop time out[%d]\n",
						__func__, u16ParserID);
					break;
				}
			}
			if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV) {
				mad_parser_tee_destroy(u16ParserID);
			}
			pTask[u16ParserID] = 0;
			if (pTaskArg[u16ParserID] != NULL) {
				kfree(pTaskArg[u16ParserID]);
				pTaskArg[u16ParserID] = NULL;
			}

			parser_mad->mad->init_flag[u16ParserID] = 0;
			parser_mad->mad->pts_wridx[u16ParserID] = 0;
			parser_mad->mad->pts_rdidx[u16ParserID] = 0;
			parser_mad->mad->u32first_pts_present[u16ParserID] = 0;
			parser_mad->mad->u32es_find_pts_flag[u16ParserID] = 0;
			parser_mad->mad->u32es_wrptr[u16ParserID] = 0;
			parser_mad->mad->pts_wridx[u16ParserID] = 0;
			parser_mad->mad->pts_rdidx[u16ParserID] = 0;
			parser_mad->mad->PtsTb[u16ParserID].u32EsWptr[0] = 0;
			parser_mad->mad->dvb2_buf[u16ParserID] = NULL;
			parser_mad->mad->u32thread_stop[u16ParserID] = 0;
			parser_mad->mad->u32secure_es_wrptr[u16ParserID] = 0;
			parser_mad->mad->u32thread_es_pollingcnt[u16ParserID] = 0;
			parser_mad->mad->u32thread_pre_es_memcnt[u16ParserID] = 0;
			parser_mad->mad->u64writeEScount[u16ParserID] = 0;
			parser_mad->mad->u64readEScount[u16ParserID] = 0;
			parser_mad->mad->es_accum[u16ParserID] = 0;
			parser_mad->mad->u32PipeId[u16ParserID] = 0;
			parser_mad->mad->u32writePreEScount[u16ParserID] = 0;
			parser_mad->mad->es_accum2[u16ParserID] = 0;
			if (parser_mad->mad->filter_type[u16ParserID] == DMX2_FILTER_TYPE_TLV) {
				parser_mad->mad->tlv_wridx_s[u16ParserID] = 0;
				parser_mad->mad->tlv_rdidx_s[u16ParserID] = 0;
				mtk_dmx_rm_put_buf(&dmxdev->rm, &parser_mad->mad->mad_buffer[u16ParserID]);
			}
			/*deinit mad hardware*/
			_mad_exit(u16ParserID);
		}
	}

	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO, "%s [%d]\n",
		__func__, u16ParserID);
	return 1;
}

int audio_parser_qbuf(u16 u16ParserID, struct dmx2_buffer *pBuf)
{
	u64 es_memcnt = 0, es_memcnt_update = 0, es_memcnt_cur = 0;
	if (u16ParserID >= MAX_MAD_NUM || parser_mad == NULL || pBuf == NULL) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "id: %d\n", u16ParserID);
		return -1;
	}

	if ((pBuf->bytesused <= parser_mad->mad->u32ParserBufSize[u16ParserID]) &&
		(pBuf->bytesused != 0) &&
		(parser_mad->mad->u64readEScount[u16ParserID] != pBuf->bytesused)) {
		if (pBuf->bytesused >= parser_mad->mad->u64readEScount[u16ParserID])
			es_memcnt_update = pBuf->bytesused -
				parser_mad->mad->u64readEScount[u16ParserID];
		else
			es_memcnt_update = parser_mad->mad->u32ParserBufSize[u16ParserID] -
				parser_mad->mad->u64readEScount[u16ParserID] + pBuf->bytesused;

		parser_mad->mad->u64readEScount[u16ParserID] = pBuf->bytesused;
	} else
		return 0;

	parser_mad->mad->es_accum[u16ParserID] +=
		(es_memcnt_update%BIT_PER_LINE);

	es_memcnt =  (es_memcnt_update>>Bitshift4);
	if (parser_mad->mad->es_accum[u16ParserID] >= BIT_PER_LINE) {
		es_memcnt++;
		parser_mad->mad->es_accum[u16ParserID] -= BIT_PER_LINE;
	}

	_DRV_MAD_Lock(u16ParserID);
	switch (u16ParserID) {
	case mad_0:
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
		udelay(sleeptime);
		es_memcnt_cur = MAD_RIU_READ_WORD(REG_PASA_DMA_DRAM_LEVEL_CNT);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_5_, 0x0000);
		if (es_memcnt > es_memcnt_cur) {
			es_memcnt_update = 0;
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
			"[%s] es mem= 0x%llx, 0x%llx\n",
			__func__, es_memcnt, es_memcnt_cur);
			break;
		}
		MAD_RIU_WRITE_WORD(REG_PASA_DMA_MCU_READ_SIZE,
		(es_memcnt));
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_4_, _BIT_4_);
		udelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASA_DMA_CTRL, _BIT_4_, 0x0000);
		break;
	case mad_1:
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
		udelay(sleeptime);
		es_memcnt_cur = MAD_RIU_READ_WORD(REG_PASB_DMA_DRAM_LEVEL_CNT);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_5_, 0x0000);
		if (es_memcnt > es_memcnt_cur) {
			es_memcnt_update = 0;
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
			"[%s] es mem= 0x%llx, 0x%llx\n",
			__func__, es_memcnt, es_memcnt_cur);
			break;
		}
		MAD_RIU_WRITE_WORD(REG_PASB_DMA_MCU_READ_SIZE,
		(es_memcnt));
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_4_, _BIT_4_);
		udelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASB_DMA_CTRL, _BIT_4_, 0x0000);
		break;
	case mad_2:
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
		udelay(sleeptime);
		es_memcnt_cur = MAD_RIU_READ_WORD(REG_PASC_DMA_DRAM_LEVEL_CNT);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_5_, 0x0000);
		if (es_memcnt > es_memcnt_cur) {
			es_memcnt_update = 0;
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
			"[%s] es mem= 0x%llx, 0x%llx\n",
			__func__, es_memcnt, es_memcnt_cur);
			break;
		}
		MAD_RIU_WRITE_WORD(REG_PASC_DMA_MCU_READ_SIZE,
		(es_memcnt));
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_4_, _BIT_4_);
		udelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASC_DMA_CTRL, _BIT_4_, 0x0000);
		break;
	case mad_3:
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_5_, _BIT_5_);  //freeze
		udelay(sleeptime);
		es_memcnt_cur = MAD_RIU_READ_WORD(REG_PASD_DMA_DRAM_LEVEL_CNT);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_5_, 0x0000);
		if (es_memcnt > es_memcnt_cur) {
			es_memcnt_update = 0;
			PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
			"[%s] es mem= 0x%llx, 0x%llx\n",
			__func__, es_memcnt, es_memcnt_cur);
			break;
		}
		MAD_RIU_WRITE_WORD(REG_PASD_DMA_MCU_READ_SIZE,
		(es_memcnt));
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_4_, _BIT_4_);
		udelay(1);
		MAD_RIU_MASK_WRITE_WORD(REG_PASD_DMA_CTRL, _BIT_4_, 0x0000);
		break;
	default:
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR,
		"%s wrong parser id\n", __func__);
		break;
	}
	parser_mad->mad->u32writePreEScount[u16ParserID] -= (es_memcnt<<Bitshift4);
	_DRV_MAD_UnLock(u16ParserID);

	PAS_DEBUG_LOG(PAS_LOG_LEVEL_INFO,
	"[%s] pBuf->bytesused = 0x%x, 0x%llx, 0x%llx,u32readcount 0x%llx,%d %u\n",
		__func__, pBuf->bytesused, es_memcnt, es_memcnt_update,
		parser_mad->mad->u64readEScount[u16ParserID],
		parser_mad->mad->es_accum[u16ParserID],
		parser_mad->mad->u32writePreEScount[u16ParserID]);
	return 0;
}

int audio_parser_dqbuf(u16 u16ParserID, struct dmx2_buffer *pBuf)
{
	if (u16ParserID >= MAX_MAD_NUM || parser_mad == NULL || pBuf == NULL) {
		PAS_DEBUG_LOG(PAS_LOG_LEVEL_ERROR, "id: %d\n", u16ParserID);
		return -1;
	}
	if (parser_mad->mad->u8BufOverflow[u16ParserID] == 1)
		pBuf->flags = 1;
	else
		pBuf->flags = 0;

	pBuf->m.fd = parser_mad->mad->s32PasOutputBufFd[u16ParserID];
	return 0;
}
