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

#include <linux/delay.h>
#include <linux/printk.h>

#include "mhal_demux_common.h"
#include "mhal_demux_regs.h"
#include "mhal_demux_alp.h"

//-------------------------------------------------------------------------------------------------
//  Debug Constants and Macros
//-------------------------------------------------------------------------------------------------
#define MHAL_DEMUX_ALP_DEBUG_ENABLE

#define MHAL_LABLE							"[MHAL_DEMUX_ALP]"
#define MHAL_DEMUX_ALP_DEBUG_CHANGED		(1)

#define MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_INTEGER(value_name, value_old, value_new) \
	({ \
		int __changed = 0; \
		if ((value_old) != (value_new)) { \
			MHAL_DEMUX_DEBUG( \
				"[%s][%d] %s is changed from (0x%x) to (0x%x).\n", \
				__func__, \
				__LINE__, \
				#value_name, \
				(int) value_old, \
				(int) value_new); \
			__changed = MHAL_DEMUX_ALP_DEBUG_CHANGED; \
		} \
		__changed; \
	})

#define MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_MEM(mem_name, mem_old, mem_new, mem_size) \
	({ \
		int __changed = 0; \
		int __i; \
		u8 *__pu8MemOld = (u8 *) mem_old; \
		u8 *__pu8MemNew = (u8 *) mem_new; \
		for (__i = 0; __i < mem_size; __i++) { \
			if (__pu8MemOld[__i] != __pu8MemNew[__i]) { \
				MHAL_DEMUX_DEBUG( \
					"[%s][%d] %s[%d] is changed from (0x%x) to (0x%x).\n", \
					__func__, \
					__LINE__, \
					#mem_name, \
					__i, \
					(int) __pu8MemOld[__i], \
					(int) __pu8MemNew[__i]); \
				__changed = MHAL_DEMUX_ALP_DEBUG_CHANGED; \
				break; \
			} \
		} \
		__changed; \
	})

#define MHAL_DEMUX_ALP_DEBUG_NAME_MAX		(128)

//-------------------------------------------------------------------------------------------------
//  Constants
//-------------------------------------------------------------------------------------------------
#ifndef true
#define true 1
#define false 0
#endif

// TODO
#define MHAL_DEMUX_ALP_KEY_WORD_0_DEFAULT	(0x47)
#define MHAL_DEMUX_ALP_KEY_WORD_1_DEFAULT	(0x47)
#define MHAL_DEMUX_ALP_KEY_WORD_2_DEFAULT	(0x47)
#define MHAL_DEMUX_ALP_KEY_WORD_3_DEFAULT	(0x47)

//-------------------------------------------------------------------------------------------------
//  Macros
//-------------------------------------------------------------------------------------------------
#define MHAL_DEMUX_ALP_CHECK_RANGE(min, max, value) \
	({ \
		int __ret = MHAL_DEMUX_SUCCESS; \
		if (((value) < (min)) || \
			((value) > (max))) { \
			__ret = MHAL_DEMUX_FAIL; \
			MHAL_DEMUX_ERR( \
				"[%s][%d] value(0x%x) is not within range(0x%x, 0x%x).\n", \
				__func__, \
				__LINE__, \
				value, \
				min, \
				max); \
		} \
		__ret; \
	})

#define MHAL_DEMUX_ALP_BASE(base, offset)	((base) + (offset))

#define COUNT_OF(x)						(sizeof(x)/sizeof(0[x]))

// TODO:
#define TOGGLE_TIME							(1) //ms

#define ENABLE								(1)
#define DISABLE								(0)
#define TRUE_TO_1(enable)					((enable) ? ENABLE : DISABLE)

//-------------------------------------------------------------------------------------------------
//  Structs and Enums
//-------------------------------------------------------------------------------------------------
#ifdef MHAL_DEMUX_ALP_DEBUG_ENABLE
struct debug_change;

typedef int (*mhal_demux_alp_debug_change_check_data_callback)(
		demux_alp_instance_e eInstance, struct debug_change *pstDebugChange, void *pvNew);
typedef void* (*mhal_demux_alp_debug_change_get_data_callback)(
		demux_alp_instance_e eInstance, struct debug_change *pstDebugChange);

typedef struct debug_change {
	bool bFirstSet;
	void *pvData;
	size_t stDataSize;

	mhal_demux_alp_debug_change_check_data_callback pfCheckDataCallback;
	mhal_demux_alp_debug_change_get_data_callback pfGetDataCallback;

} debug_change_t;

typedef enum {
	DEBUG_BANK_TYPE_MIN = 0,

	DEBUG_BANK_TYPE_ALP_0 = DEBUG_BANK_TYPE_MIN,
	DEBUG_BANK_TYPE_TS_SAMPLE,

	DEBUG_BANK_TYPE_MAX,
} debug_bank_type_e;

typedef struct {
	debug_bank_type_e eBankType;
	u32 offset;
	char names[MHAL_DEMUX_ALP_DEBUG_NAME_MAX];
} debug_regs_t;
#endif //#ifdef MHAL_DEMUX_ALP_DEBUG_ENABLE

typedef struct offsets {
	u32 *offsets;
	u8 min;
	u8 max;
} offsets_t;

typedef enum {
	MHAL_DEMUX_ALP_DEBUG_CHANGE_MIN = 0,
	MHAL_DEMUX_ALP_DEBUG_CHANGE_FOR_KEY_WORD = MHAL_DEMUX_ALP_DEBUG_CHANGE_MIN,
	MHAL_DEMUX_ALP_DEBUG_CHANGE_FOR_FILTER,

	MHAL_DEMUX_ALP_DEBUG_CHANGE_MAX,
} mhal_demux_alp_debug_change_e;

//-------------------------------------------------------------------------------------------------
//  Functions Prototype
//-------------------------------------------------------------------------------------------------
static int _mhal_demux_alp_debug_change_check_data_callback_for_key_words(
	demux_alp_instance_e eInstance, debug_change_t *pstDebugChange, void *pvNew);
static void *_mhal_demux_alp_debug_change_get_data_callback_for_key_words(
	demux_alp_instance_e eInstance, debug_change_t *pstDebugChange);

static int _mhal_demux_alp_debug_change_check_data_callback_for_filter(
	demux_alp_instance_e eInstance, debug_change_t *pstDebugChange, void *pvNew);
static void *_mhal_demux_alp_debug_change_get_data_callback_for_filter(
	demux_alp_instance_e eInstance, debug_change_t *pstDebugChange);

//-------------------------------------------------------------------------------------------------
//  Variables
//-------------------------------------------------------------------------------------------------
static demux_alp_filter_t _stFilter[DEMUX_ALP_INSTANCE_MAX][DEMUX_ALP_IP_FILTER_MAX] = {{0}};

#ifdef MHAL_DEMUX_ALP_DEBUG_ENABLE
static demux_alp_key_words_t _stKeyWordsForDebugChange[DEMUX_ALP_INSTANCE_MAX] = {{0}};

static debug_change_t _stDebugChanges[MHAL_DEMUX_ALP_DEBUG_CHANGE_MAX] = {
	// MHAL_DEMUX_ALP_DEBUG_CHANGE_FOR_KEY_WORD
	{
		.bFirstSet = true,
		.pvData = _stKeyWordsForDebugChange,
		.stDataSize = sizeof(demux_alp_key_words_t),
		.pfCheckDataCallback =
			_mhal_demux_alp_debug_change_check_data_callback_for_key_words,
		.pfGetDataCallback = _mhal_demux_alp_debug_change_get_data_callback_for_key_words,
	},
	// MHAL_DEMUX_ALP_DEBUG_CHANGE_FOR_FILTER
	{
		.bFirstSet = true,
		.pvData = _stFilter,
		.stDataSize = sizeof(demux_alp_filter_t),
		.pfCheckDataCallback = _mhal_demux_alp_debug_change_check_data_callback_for_filter,
		.pfGetDataCallback = _mhal_demux_alp_debug_change_get_data_callback_for_filter,
	},
};

static const char *szBitRep[16] = {
	[0] = "0000", [1] = "0001", [2] = "0010", [3] = "0011",
	[4] = "0100", [5] = "0101", [6] = "0110", [7] = "0111",
	[8] = "1000", [9] = "1001", [10] = "1010", [11] = "1011",
	[12] = "1100", [13] = "1101", [14] = "1110", [15] = "1111",
};

static debug_regs_t stDebugSetupRegs[] = {
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0034_TSP_ALP,
		"REG_RECORD_ALL_ALP_FORMAT[11], REG_RECORD_TIMESTAMP_KEYWORD_EN[12]",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_006C_TSP_ALP,
		"REG_ALP_PROCESS_ENABLE[0], REG_INSERT_KEY_WORD_SEL[5:3]",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0070_TSP_ALP,
		"REG_KEY_WORD0[7:0], REG_KEY_WORD1[15:8]",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0080_TSP_ALP,
		"REG_ALP_ENABLE[2]",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0084_TSP_ALP,
		"REG_FMR_CONFIG0_IN_0[15:0]",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0088_TSP_ALP,
		"REG_FMR_CONFIG0_IN_1[2:0]",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0180_TSP_ALP,
		"REG_IP_SOURCE_ADDR_NTP_0",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0184_TSP_ALP,
		"REG_IP_SOURCE_ADDR_NTP_1",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0188_TSP_ALP,
		"REG_IP_SOURCE_ADDR_NTP_2",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_018C_TSP_ALP,
		"REG_IP_SOURCE_ADDR_NTP_3",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0190_TSP_ALP,
		"REG_IP_SOURCE_ADDR_NTP_4",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0194_TSP_ALP,
		"REG_IP_SOURCE_ADDR_NTP_5",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_0198_TSP_ALP,
		"REG_IP_SOURCE_ADDR_NTP_6",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_019C_TSP_ALP,
		"REG_IP_SOURCE_ADDR_NTP_7",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_01C0_TSP_ALP,
		"REG_MTK_ALP_CONFIG0_RESET_N_IN[2:0]",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_01C4_TSP_ALP,
		"REG_MTK_ALP_CONFIG1_SELECT_MTK_ALP_TOP_OUTPUT[1], REG_MTK_ALP_CONFIG1_SIDEBAND_EN[2]",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_01C8_TSP_ALP,
		"REG_MTK_ALP_CONFIG2_ALP_FILEIN_TOP[5:4]",
	},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_01CC_TSP_ALP,
		"REG_MTK_ALP_CONFIG3_MTK_ALP_TOP[0]",
	},
	{
		DEBUG_BANK_TYPE_TS_SAMPLE,
		REG_0144_TS_SAMPLE,
		"REG_CKG_TS_ALP0[7:0], REG_CKG_TS_ALP1[15:8]",
	},
	{
		DEBUG_BANK_TYPE_TS_SAMPLE,
		REG_0148_TS_SAMPLE,
		"REG_CKG_TS_ALP2[7:0], REG_CKG_TS_ALP_FI[15:8]",
	},
};

static debug_regs_t stDebugAlpFilterRegs[] = {
	{DEBUG_BANK_TYPE_ALP_0, REG_00C0_TSP_ALP, "REG_IP_SOURCE_ADDR_MMTP_0"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00C4_TSP_ALP, "REG_IP_SOURCE_ADDR_MMTP_1"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00C8_TSP_ALP, "REG_IP_SOURCE_ADDR_MMTP_2"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00CC_TSP_ALP, "REG_IP_SOURCE_ADDR_MMTP_3"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00D0_TSP_ALP, "REG_IP_SOURCE_ADDR_MMTP_4"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00D4_TSP_ALP, "REG_IP_SOURCE_ADDR_MMTP_5"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00D8_TSP_ALP, "REG_IP_SOURCE_ADDR_MMTP_6"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00DC_TSP_ALP, "REG_IP_SOURCE_ADDR_MMTP_7"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00E0_TSP_ALP, "REG_IP_DES_ADDR_MMTP_0"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00E4_TSP_ALP, "REG_IP_DES_ADDR_MMTP_1"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00E8_TSP_ALP, "REG_IP_DES_ADDR_MMTP_2"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00EC_TSP_ALP, "REG_IP_DES_ADDR_MMTP_3"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00F0_TSP_ALP, "REG_IP_DES_ADDR_MMTP_4"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00F4_TSP_ALP, "REG_IP_DES_ADDR_MMTP_5"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00F8_TSP_ALP, "REG_IP_DES_ADDR_MMTP_6"},
	{DEBUG_BANK_TYPE_ALP_0, REG_00FC_TSP_ALP, "REG_IP_DES_ADDR_MMTP_7"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0100_TSP_ALP, "udp_port des REG_UDP_PORT_MMTP_0"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0104_TSP_ALP, "udp_port src REG_UDP_PORT_MMTP_1"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0108_TSP_ALP, "udp_port mask des REG_UDP_PORT_MMTP1_0"},
	{DEBUG_BANK_TYPE_ALP_0, REG_010C_TSP_ALP, "udp_port mask src REG_UDP_PORT_MMTP1_1"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0140_TSP_ALP, "mask REG_IP_SOURCE_ADDR_MMTP1_0"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0144_TSP_ALP, "mask REG_IP_SOURCE_ADDR_MMTP1_1"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0148_TSP_ALP, "mask REG_IP_SOURCE_ADDR_MMTP1_2"},
	{DEBUG_BANK_TYPE_ALP_0, REG_014C_TSP_ALP, "mask REG_IP_SOURCE_ADDR_MMTP1_3"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0150_TSP_ALP, "mask REG_IP_SOURCE_ADDR_MMTP1_4"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0154_TSP_ALP, "mask REG_IP_SOURCE_ADDR_MMTP1_5"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0158_TSP_ALP, "mask REG_IP_SOURCE_ADDR_MMTP1_6"},
	{DEBUG_BANK_TYPE_ALP_0, REG_015C_TSP_ALP, "mask REG_IP_SOURCE_ADDR_MMTP1_7"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0160_TSP_ALP, "mask REG_IP_DES_ADDR_MMTP1_0"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0164_TSP_ALP, "mask REG_IP_DES_ADDR_MMTP1_1"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0168_TSP_ALP, "mask REG_IP_DES_ADDR_MMTP1_2"},
	{DEBUG_BANK_TYPE_ALP_0, REG_016C_TSP_ALP, "mask REG_IP_DES_ADDR_MMTP1_3"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0170_TSP_ALP, "mask REG_IP_DES_ADDR_MMTP1_4"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0174_TSP_ALP, "mask REG_IP_DES_ADDR_MMTP1_5"},
	{DEBUG_BANK_TYPE_ALP_0, REG_0178_TSP_ALP, "mask REG_IP_DES_ADDR_MMTP1_6"},
	{DEBUG_BANK_TYPE_ALP_0, REG_017C_TSP_ALP, "mask REG_IP_DES_ADDR_MMTP1_7"},
	{DEBUG_BANK_TYPE_ALP_0, REG_01A4_TSP_ALP, "REG_SINGLE_PLP_MODE[15]"},
	{DEBUG_BANK_TYPE_ALP_0, REG_01A8_TSP_ALP, "REG_CID[7:0], REG_SID[15:8]"},
	{
		DEBUG_BANK_TYPE_ALP_0,
		REG_01AC_TSP_ALP,
		"REG_PLP_ID[5:0], REG_COMP_FLAG[8], REG_SID_FLAG[9], REG_PLP_MASK[10]",
	},
	{DEBUG_BANK_TYPE_ALP_0, REG_01B0_TSP_ALP, "REG_MTK_ALP_I[7:0]"},
	{DEBUG_BANK_TYPE_ALP_0, REG_01B4_TSP_ALP, "REG_FMR_TLV_CID23_1"},
};

static debug_regs_t stDebugAlpFilterEnableRegs[] = {
	{DEBUG_BANK_TYPE_ALP_0, REG_01B8_TSP_ALP, "enable_filter REG_FMR_TLV_CID45_0"},
	{DEBUG_BANK_TYPE_ALP_0, REG_01BC_TSP_ALP, "enable_filter REG_FMR_TLV_CID45_1"},
};

#endif //MHAL_DEMUX_ALP_DEBUG_ENABLE

//-------------------------------------------------------------------------------------------------
//  Internal Functions
//-------------------------------------------------------------------------------------------------
#ifdef MHAL_DEMUX_ALP_DEBUG_ENABLE
static int _mhal_demux_alp_print_bytes(const char *szTitle, u8 *pu8Addr, u8 u8Size)
{
	u8 u8Index = 0;

	if (pu8Addr == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pu8Addr is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}
	if (u8Size == 0) {
		MHAL_DEMUX_ERR(
			"[%s][%d] u8Size is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}

	if ((szTitle != NULL) && (strlen(szTitle) > 0)) {
		MHAL_DEMUX_DEBUG(
			"[%s]\n",
			szTitle);
	}
	for (u8Index = 0; u8Index < u8Size; u8Index++) {
		MHAL_DEMUX_DEBUG(
			"[%u]0x%x ",
			(unsigned int)u8Index,
			(unsigned int)pu8Addr[u8Index]);
	}

	MHAL_DEMUX_DEBUG("\n");

	return 0;
}
#else
static int _mhal_demux_alp_print_bytes(const char *szTitle, u8 *pu8Addr, u8 u8Size)
{
	return 0;
}
#endif //#if MHAL_DEMUX_ALP_DEBUG_ENABLE

#ifdef MHAL_DEMUX_ALP_DEBUG_ENABLE
void _mhal_demux_alp_debug_change(
	demux_alp_instance_e eInstance, debug_change_t *pstDebugChange, void *pvNewData)
{
	int iChange = 0;
	void *pvOldData = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return;
	if (pstDebugChange == NULL)
		return;
	if (pvNewData == NULL)
		return;
	pvOldData = pstDebugChange->pfGetDataCallback(eInstance, pstDebugChange);
	if (pvOldData == NULL)
		return;

	if (pstDebugChange->bFirstSet) {
		memcpy(pvOldData, pvNewData, pstDebugChange->stDataSize);
		pstDebugChange->bFirstSet = false;
		return;
	}

	iChange = pstDebugChange->pfCheckDataCallback(eInstance, pstDebugChange, pvNewData);
/*
 * For debug use to trace caller
 *	if (iChange)
 *		dump_stack();
 */

	memcpy(pvOldData, pvNewData, pstDebugChange->stDataSize);
}

#else
void _mhal_demux_alp_debug_change(
	demux_alp_instance_e eInstance, debug_change_t *pstDebugChange, void *pvNew)
{

}
#endif //#ifdef MHAL_DEMUX_ALP_DEBUG_ENABLE

#ifdef MHAL_DEMUX_ALP_DEBUG_ENABLE
int _mhal_demux_alp_debug_change_check_data_callback_for_key_words(
	demux_alp_instance_e eInstance, debug_change_t *pstDebugChange, void *pvNew)
{
	int iChange = 0;
	demux_alp_key_words_t *pstOld = NULL;
	demux_alp_key_words_t *pstNew = (demux_alp_key_words_t *)pvNew;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return 0;
	if (pstDebugChange == NULL)
		return 0;
	if (pvNew == NULL)
		return 0;
	if (pstDebugChange->pvData == NULL)
		return 0;
	pstOld = pstDebugChange->pfGetDataCallback(eInstance, pstDebugChange);
	if (pstOld == NULL)
		return 0;

	iChange = MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_INTEGER(
				  eKeyWordType,
				  pstOld->eKeyWordType,
				  pstNew->eKeyWordType);

	iChange |= MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_MEM(
				  u8keyWords,
				  pstOld->u8keyWords,
				  pstNew->u8keyWords,
				  sizeof(pstOld->u8keyWords));

	iChange |= MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_INTEGER(
				  bSidebandEnable,
				  pstOld->bSidebandEnable,
				  pstNew->bSidebandEnable);

	return iChange;
}

static void *_mhal_demux_alp_debug_change_get_data_callback_for_key_words(
	demux_alp_instance_e eInstance, debug_change_t *pstDebugChange)
{
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return NULL;

	return &((demux_alp_key_words_t *)pstDebugChange->pvData)[eInstance];
}

int _mhal_demux_alp_debug_change_check_data_callback_for_filter(
	demux_alp_instance_e eInstance, debug_change_t *pstDebugChange, void *pvNew)
{
	int iChange = 0;
	demux_alp_filter_t *pstOld = NULL;
	demux_alp_filter_t *pstNew = (demux_alp_filter_t *)pvNew;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return 0;
	if (pstDebugChange == NULL)
		return 0;
	if (pvNew == NULL)
		return 0;
	if (pstDebugChange->pvData == NULL)
		return 0;
	pstOld = pstDebugChange->pfGetDataCallback(eInstance, pstDebugChange);
	if (pstOld == NULL)
		return 0;

	iChange |= MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_MEM(
				   stSrcAddr,
				   &pstOld[pstNew->s8Index].stSrcAddr,
				   &pstNew->stSrcAddr,
				   sizeof(pstOld->stSrcAddr));

	iChange |= MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_MEM(
				   stDesAddr,
				   &pstOld[pstNew->s8Index].stDesAddr,
				   &pstNew->stDesAddr,
				   sizeof(pstOld->stDesAddr));

	iChange |= MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_MEM(
				   stSrcPort,
				   &pstOld[pstNew->s8Index].stSrcPort,
				   &pstNew->stSrcPort,
				   sizeof(pstOld->stSrcPort));

	iChange |= MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_MEM(
				   stDesPort,
				   &pstOld[pstNew->s8Index].stDesPort,
				   &pstNew->stDesPort,
				   sizeof(pstOld->stDesPort));

	iChange |= MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_MEM(
				   stPlp,
				   &pstOld[pstNew->s8Index].stPlp,
				   &pstNew->stPlp,
				   sizeof(pstOld->stPlp));

	iChange |= MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_MEM(
				   stSid,
				   &pstOld[pstNew->s8Index].stSid,
				   &pstNew->stSid,
				   sizeof(pstOld->stSid));

	iChange |= MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_MEM(
				   stCid,
				   &pstOld[pstNew->s8Index].stCid,
				   &pstNew->stCid,
				   sizeof(pstOld->stCid));

	iChange |= MHAL_DEMUX_ALP_DEBUG_PRINT_CHANGED_FOR_INTEGER(
				   u8FilterId,
				   pstOld[pstNew->s8Index].u8FilterId,
				   pstNew->u8FilterId);

	return iChange;
}

static void *_mhal_demux_alp_debug_change_get_data_callback_for_filter(
	demux_alp_instance_e eInstance, debug_change_t *pstDebugChange)
{
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return NULL;

	return &((demux_alp_filter_t *)pstDebugChange->pvData)[eInstance];
}
#endif //#ifdef MHAL_DEMUX_ALP_DEBUG_ENABLE

#ifdef MHAL_DEMUX_ALP_DEBUG_ENABLE
static REG16 __iomem *_mhal_demux_alp_debug_get_base(debug_bank_type_e eBankType)
{
	REG16 __iomem *pBase = NULL;

	switch (eBankType) {
	case DEBUG_BANK_TYPE_ALP_0:
		pBase = REG_BASE_ALP(0);
		break;
	case DEBUG_BANK_TYPE_TS_SAMPLE:
		pBase = REG_TS_SAMPLE_BASE;
		break;
	default:
		break;
	}

	return pBase;
}

void _mhal_demux_alp_print_u16_2_binary(u16 u16Word)
{
	MHAL_DEMUX_DEBUG(
		"%s %s %s %s",
		szBitRep[u16Word >> 12],
		szBitRep[u16Word >> 8 & 0x0F],
		szBitRep[u16Word >> 4 & 0x0F],
		szBitRep[u16Word & 0x0F]);
}

static void _mhal_demux_alp_print_regs(debug_regs_t *pstDebugRegs, size_t size)
{
	int i = 0;
	REG16 __iomem *pBase = NULL;
	u16 u16Value = 0;

	for (i = 0; i < size; i++) {
		pBase = _mhal_demux_alp_debug_get_base(pstDebugRegs[i].eBankType);
		if (pBase == NULL)
			continue;

		u16Value = u2IO32Read2B(MHAL_DEMUX_ALP_BASE(pBase, pstDebugRegs[i].offset));
		MHAL_DEMUX_DEBUG(
			"%s\n0x%x ",
			pstDebugRegs[i].names,
			u16Value);
		_mhal_demux_alp_print_u16_2_binary(u16Value);
		MHAL_DEMUX_DEBUG("\n");
	}
}

static void _mhal_demux_alp_print_alp_filter_regs(void)
{
	MHAL_DEMUX_DEBUG("REG_BASE_ALP[0] = 0x%llx\n", (long long)REG_BASE_ALP(0));
	MHAL_DEMUX_DEBUG("REG_BASE_ALP[1] = 0x%llx\n", (long long)REG_BASE_ALP(1));
	_mhal_demux_alp_print_regs(stDebugAlpFilterRegs, COUNT_OF(stDebugAlpFilterRegs));
}

static void _mhal_demux_alp_print_alp_filter_enable_regs(void)
{
	MHAL_DEMUX_DEBUG("REG_BASE_ALP[0] = 0x%llx\n", (long long)REG_BASE_ALP(0));
	MHAL_DEMUX_DEBUG("REG_BASE_ALP[1] = 0x%llx\n", (long long)REG_BASE_ALP(1));
	_mhal_demux_alp_print_regs(
		stDebugAlpFilterEnableRegs,
		COUNT_OF(stDebugAlpFilterEnableRegs));
}

void mhal_demux_alp_print_setup_regs(void)
{
	MHAL_DEMUX_DEBUG("REG_BASE_ALP[0] = 0x%llx\n", (long long)REG_BASE_ALP(0));
	MHAL_DEMUX_DEBUG("REG_BASE_ALP[1] = 0x%llx\n", (long long)REG_BASE_ALP(1));
	MHAL_DEMUX_DEBUG("REG_TS_SAMPLE_BASE = 0x%llx\n", (long long)REG_TS_SAMPLE_BASE);
	_mhal_demux_alp_print_regs(stDebugSetupRegs, COUNT_OF(stDebugSetupRegs));
}
#else
void _mhal_demux_alp_print_alp_filter_regs(void)
{

}

static void _mhal_demux_alp_print_alp_filter_enable_regs(void)
{

}

void mhal_demux_alp_print_setup_regs(void)
{

}
#endif //#if MHAL_DEMUX_ALP_DEBUG_ENABLE

static int _mhal_demux_alp_getBase(demux_alp_instance_e eInstance, REG16 __iomem **ppBase)
{
	int iRet = MHAL_DEMUX_SUCCESS;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			REG_BANK_MAX_ALP - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	*ppBase = REG_BASE_ALP(eInstance);

	return iRet;
}

static int _mhal_demux_alp_reg32_enable(REG16 __iomem *pBasedOffset, u8 nr, bool bEnable)
{
	int iRet = MHAL_DEMUX_SUCCESS;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			0,
			31,
			nr))
		return MHAL_DEMUX_FAIL;

	if (bEnable)
		REG32_SET_BIT(pBasedOffset, nr);
	else
		REG32_CLEAR_BIT(pBasedOffset, nr);

	return iRet;
}

static int _mhal_demux_alp_reg16_write_for_array(
	REG16 __iomem *pBase, offsets_t *pstOffsets, u8 u8Index, u16 u16Value)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	uint32_t fld = Fld(16, 0, AC_FULLW10);

	if (pstOffsets == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstOffsets is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			pstOffsets->min,
			pstOffsets->max - 1,
			u8Index))
		return MHAL_DEMUX_FAIL;

	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, pstOffsets->offsets[u8Index]),
		(u32)u16Value,
		fld);

	return iRet;
}

static int _mhal_demux_alp_rewrite(REG16 __iomem *pBasedOffset)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	u32 u32Value = 0;
	uint32_t fld = Fld(16, 0, AC_FULLW10);

	if (pBasedOffset == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pBasedOffset is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}

	u32Value = u4IO32ReadFld(
				   pBasedOffset,
				   fld);

	vIO32WriteFld(
		pBasedOffset,
		u32Value,
		fld);

	return iRet;
}

static int _mhal_demux_alp_set_clock_source(
	demux_alp_instance_e eInstance, demux_alp_path_type_e ePathType)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	u32 u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_TS0;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_PATH_TYPE_LIVE_IN_MIN,
			DEMUX_ALP_PATH_TYPE_LIVE_IN_MAX - 1,
			ePathType))
		return MHAL_DEMUX_FAIL;

	switch (ePathType) {
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_FROM_TS0:
		u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_TS0;
		break;
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_FROM_TS1:
		u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_TS1;
		break;
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_FROM_TS2:
		u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_TS2;
		break;
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_FROM_TS3:
		u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_TS3;
		break;
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_FROM_TS4:
		u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_TS4;
		break;
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_FROM_TS5:
		u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_TS5;
		break;
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_FROM_TSO:
		u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_TSO;
		break;
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_FROM_CILINK1:
		u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_CILINK1;
		break;
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_FROM_CILINK2:
		u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_CILINK2;
		break;
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_FROM_DEMOD:
		u32Value = REG_CKG_TS_ALP1_CLOCK_SOURCE_DEMOD;
		break;
	default:
		break;
	}

	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(REG_TS_SAMPLE_BASE, REG_0144_TS_SAMPLE),
		1,
		REG_CKG_TS_ALP0_DISABLE_CLOCK);
	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(REG_TS_SAMPLE_BASE, REG_0148_TS_SAMPLE),
		1,
		REG_CKG_TS_ALP_FI_DISABLE_CLOCK);

	switch (eInstance) {
	case DEMUX_ALP_INSTANCE_0:
		vIO32WriteFldMulti(
			MHAL_DEMUX_ALP_BASE(REG_TS_SAMPLE_BASE, REG_0144_TS_SAMPLE),
			3,
			0,
			REG_CKG_TS_ALP0_DISABLE_CLOCK,
			0,
			REG_CKG_TS_ALP0_INVERT_CLOCK,
			u32Value,
			REG_CKG_TS_ALP0_CLOCK_SOURCE);
		break;
	case DEMUX_ALP_INSTANCE_1:
		vIO32WriteFldMulti(
			MHAL_DEMUX_ALP_BASE(REG_TS_SAMPLE_BASE, REG_0148_TS_SAMPLE),
			3,
			0,
			REG_CKG_TS_ALP_FI_DISABLE_CLOCK,
			0,
			REG_CKG_TS_ALP_FI_INVERT_CLOCK,
			u32Value,
			REG_CKG_TS_ALP_FI_CLOCK_SOURCE);
		break;
	default:
		MHAL_DEMUX_ERR(
			"[%s][%d] eInstance(0x%x) is not supported.\n",
			__func__,
			__LINE__,
			eInstance);
		iRet = MHAL_DEMUX_FAIL;
		break;
	}

	return iRet;
}

static int _mhal_demux_alp_set_path_for_live_in(
	demux_alp_instance_e eInstance, demux_alp_path_type_e ePathType)
{
	int iRet = MHAL_DEMUX_SUCCESS;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_PATH_TYPE_LIVE_IN_MIN,
			DEMUX_ALP_PATH_TYPE_LIVE_IN_MAX - 1,
			ePathType))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_set_clock_source(eInstance, ePathType);

	return iRet;
}

static int _mhal_demux_alp_set_path_for_filein(
	demux_alp_instance_e eInstance, demux_alp_path_type_e ePathType)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u16 u16Value = 0;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_PATH_TYPE_FILEIN_MIN,
			DEMUX_ALP_PATH_TYPE_FILEIN_MAX - 1,
			ePathType))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	switch (ePathType) {
	case DEMUX_ALP_PATH_TYPE_FILEIN_FROM_FILEIN0:
		u16Value = REG_MTK_ALP_CONFIG2_ALP_FILEIN_TOP_FROM_FILEIN;
		break;
	case DEMUX_ALP_PATH_TYPE_FILEIN_FROM_MMFI0:
		u16Value = REG_MTK_ALP_CONFIG2_ALP_FILEIN_TOP_FROM_MMFI0;
		break;
	case DEMUX_ALP_PATH_TYPE_FILEIN_FROM_MMFI1:
		u16Value = REG_MTK_ALP_CONFIG2_ALP_FILEIN_TOP_FROM_MMFI1;
		break;
	default:
		MHAL_DEMUX_ERR(
			"[%s][%d] ePathType(0x%x) is not supported.\n",
			__func__,
			__LINE__,
			ePathType);
		iRet = MHAL_DEMUX_FAIL;
		break;
	}

	if (iRet == MHAL_DEMUX_SUCCESS) {
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_01C8_TSP_ALP),
			ENABLE,
			REG_MTK_ALP_CONFIG2_ALP_FILEIN_ENABLE);

		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_01C8_TSP_ALP),
			u16Value,
			REG_MTK_ALP_CONFIG2_ALP_FILEIN_TOP);
	}

	return iRet;
}

static int _mhal_demux_alp_set_path_for_mtk_alp_top(
	demux_alp_instance_e eInstance, demux_alp_path_type_e ePathType)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u16 u16Value = 0;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_PATH_TYPE_MTK_ALP_TOP_MIN,
			DEMUX_ALP_PATH_TYPE_MTK_ALP_TOP_MAX - 1,
			ePathType))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	switch (ePathType) {
	case DEMUX_ALP_PATH_TYPE_MTK_ALP_TOP_FROM_TSIF_ALP:
		u16Value = REG_MTK_ALP_CONFIG3_MTK_ALP_TOP_FROM_TSIF_ALP;
		break;
	case DEMUX_ALP_PATH_TYPE_MTK_ALP_TOP_FROM_ALP_FILEIN_TOP:
		u16Value = REG_MTK_ALP_CONFIG3_MTK_ALP_TOP_FROM_ALP_FILEIN_TOP;
		break;
	default:
		MHAL_DEMUX_ERR(
			"[%s][%d] ePathType(0x%x) is not supported.\n",
			__func__,
			__LINE__,
			ePathType);
		iRet = MHAL_DEMUX_FAIL;
		break;
	}

	if (iRet == MHAL_DEMUX_SUCCESS)
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_01CC_TSP_ALP),
			u16Value,
			REG_MTK_ALP_CONFIG3_MTK_ALP_TOP);

	return iRet;
}

static int _mhal_demux_alp_set_path_for_fifo_before_pvr(
	demux_alp_instance_e eInstance, demux_alp_path_type_e ePathType)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_PATH_TYPE_FIFO_BEFORE_PVR_MIN,
			DEMUX_ALP_PATH_TYPE_FIFO_BEFORE_PVR_MAX - 1,
			ePathType))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	switch (ePathType) {
	case DEMUX_ALP_PATH_TYPE_FIFO_BEFORE_PVR_FROM_TSIF_ALP:
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_0034_TSP_ALP),
			1,
			REG_RECORD_ALL_ALP_FORMAT);
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_006C_TSP_ALP),
			0,
			REG_ALP_PROCESS_ENABLE);
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_01C4_TSP_ALP),
			0,
			REG_MTK_ALP_CONFIG1_SELECT_MTK_ALP_TOP_OUTPUT);
		break;
	case DEMUX_ALP_PATH_TYPE_FIFO_BEFORE_PVR_FROM_ALP_PROCESS:
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_0034_TSP_ALP),
			0,
			REG_RECORD_ALL_ALP_FORMAT);
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_006C_TSP_ALP),
			1,
			REG_ALP_PROCESS_ENABLE);
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_01C4_TSP_ALP),
			0,
			REG_MTK_ALP_CONFIG1_SELECT_MTK_ALP_TOP_OUTPUT);
		break;
	case DEMUX_ALP_PATH_TYPE_FIFO_BEFORE_PVR_FROM_MTK_ALP_TOP:
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_0034_TSP_ALP),
			0,
			REG_RECORD_ALL_ALP_FORMAT);
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_006C_TSP_ALP),
			0,
			REG_ALP_PROCESS_ENABLE);
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_01C4_TSP_ALP),
			1,
			REG_MTK_ALP_CONFIG1_SELECT_MTK_ALP_TOP_OUTPUT);
		break;
	default:
		MHAL_DEMUX_ERR(
			"[%s][%d] ePathType(0x%x) is not supported.\n",
			__func__,
			__LINE__,
			ePathType);
		iRet = MHAL_DEMUX_FAIL;
		break;
	}

	return iRet;
}

static int _mhal_demux_alp_set_path_for_alp_out_fifo(
	demux_alp_instance_e eInstance, demux_alp_path_type_e ePathType)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_PATH_TYPE_ALP_OUT_FIFO_MIN,
			DEMUX_ALP_PATH_TYPE_ALP_OUT_FIFO_MAX - 1,
			ePathType))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	switch (ePathType) {
	case DEMUX_ALP_PATH_TYPE_ALP_OUT_FIFO_FROM_FIFO_BEFORE_PVR:
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_0034_TSP_ALP),
			0,
			REG_RECORD_TIMESTAMP_KEYWORD_EN);
		break;
	case DEMUX_ALP_PATH_TYPE_ALP_OUT_FIFO_FROM_TIMESTAM_KEYWORD_SIDEBAND_INSERT:
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_0034_TSP_ALP),
			1,
			REG_RECORD_TIMESTAMP_KEYWORD_EN);
		break;
	default:
		MHAL_DEMUX_ERR(
			"[%s][%d] ePathType(0x%x) is not supported.\n",
			__func__,
			__LINE__,
			ePathType);
		iRet = MHAL_DEMUX_FAIL;
		break;
	}

	return iRet;
}

static int _mhal_demux_alp_set_key_word(demux_alp_instance_e eInstance, u8 u8Index, u8 u8KeyWord)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u16 u16Value = (u16)u8KeyWord;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			0,
			DEMUX_ALP_KEY_WORD_MAX - 1,
			u8Index))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	switch (u8Index) {
	case 0:
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_0070_TSP_ALP),
			u16Value,
			REG_KEY_WORD0);
		break;
	case 1:
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_0070_TSP_ALP),
			u16Value,
			REG_KEY_WORD1);
		break;
	case 2:
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_0050_TSP_ALP),
			u16Value,
			REG_KEY_WORD2);
		break;
	case 3:
		vIO32WriteFld(
			MHAL_DEMUX_ALP_BASE(pBase, REG_0050_TSP_ALP),
			u16Value,
			REG_KEY_WORD3);
		break;
	default:
		MHAL_DEMUX_ERR(
			"[%s][%d] u8Index(0x%x) is not supported.\n",
			__func__,
			__LINE__,
			u8Index);
		iRet = MHAL_DEMUX_FAIL;
		break;
	}

	return iRet;
}

static int _mhal_demux_alp_enable_sideband(demux_alp_instance_e eInstance, bool bEnable)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01C4_TSP_ALP),
		TRUE_TO_1(bEnable),
		REG_MTK_ALP_CONFIG1_SIDEBAND_EN);

	return iRet;
}

static int _mhal_demux_alp_set_reset_n_in(demux_alp_instance_e eInstance, u16 u16Value)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01C0_TSP_ALP),
		u16Value,
		REG_MTK_ALP_CONFIG0_RESET_N_IN);

	return iRet;
}

static int _mhal_demux_alp_enable_alp(demux_alp_instance_e eInstance, bool bEnable)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_0080_TSP_ALP),
		TRUE_TO_1(bEnable),
		REG_ALP_ENABLE);

	return iRet;
}

static int _mhal_demux_alp_set_serial_framer_config0(demux_alp_instance_e eInstance, u32 u32Value)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	MHAL_DEMUX_DEBUG("[%s][%d] 0x%x\n", __func__, __LINE__, u32Value);

	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_0084_TSP_ALP),
		u32Value & 0xFFFF,
		REG_FMR_CONFIG0_IN_0);
	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_0088_TSP_ALP),
		u32Value >> 16,
		REG_FMR_CONFIG0_IN_1);

	return iRet;
}

static int _mhal_demux_alp_set_ip_source_addr_ntp(
	demux_alp_instance_e eInstance, u8 u8Index, u16 u16Value)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u32 offsets[] = {
		REG_0180_TSP_ALP, //REG_IP_SOURCE_ADDR_NTP_0
		REG_0184_TSP_ALP, //REG_IP_SOURCE_ADDR_NTP_1
		REG_0188_TSP_ALP, //REG_IP_SOURCE_ADDR_NTP_2
		REG_018C_TSP_ALP, //REG_IP_SOURCE_ADDR_NTP_3
		REG_0190_TSP_ALP, //REG_IP_SOURCE_ADDR_NTP_4
		REG_0194_TSP_ALP, //REG_IP_SOURCE_ADDR_NTP_5
		REG_0198_TSP_ALP, //REG_IP_SOURCE_ADDR_NTP_6
		REG_019C_TSP_ALP, //REG_IP_SOURCE_ADDR_NTP_7
	};
	offsets_t stOffsets = {
		.offsets = offsets,
		.min = 0,
		.max = ARRAY_SIZE(offsets),
	};

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance)) {
		return MHAL_DEMUX_FAIL;
	}

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	return _mhal_demux_alp_reg16_write_for_array(
			   pBase,
			   &stOffsets,
			   u8Index,
			   u16Value);
}

static int _mhal_demux_alp_serial_framer_init(demux_alp_instance_e eInstance)
{
	int iRet = MHAL_DEMUX_SUCCESS;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance)) {
		return MHAL_DEMUX_FAIL;
	}

	_mhal_demux_alp_enable_alp(eInstance, true);
	_mhal_demux_alp_set_serial_framer_config0(eInstance, 0x00000002);

	_mhal_demux_alp_set_ip_source_addr_ntp(eInstance, 0, 0x0000);
	_mhal_demux_alp_set_ip_source_addr_ntp(eInstance, 1, 0x0000);
	_mhal_demux_alp_set_ip_source_addr_ntp(eInstance, 2, 0x4fff);
	_mhal_demux_alp_set_ip_source_addr_ntp(eInstance, 3, 0x030e);
	_mhal_demux_alp_set_ip_source_addr_ntp(eInstance, 4, 0x60c7);
	_mhal_demux_alp_set_ip_source_addr_ntp(eInstance, 5, 0x1404);
	_mhal_demux_alp_set_ip_source_addr_ntp(eInstance, 6, 0x0320);
	_mhal_demux_alp_set_ip_source_addr_ntp(eInstance, 7, 0x0000);

	return iRet;
}

static int _mhal_demux_alp_set_ip_source_addr(
	demux_alp_instance_e eInstance, u8 u8Index, u16 u16Value)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u32 offsets[] = {
		REG_00C0_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP_0
		REG_00C4_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP_1
		REG_00C8_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP_2
		REG_00CC_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP_3
		REG_00D0_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP_4
		REG_00D4_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP_5
		REG_00D8_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP_6
		REG_00DC_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP_7
	};
	offsets_t stOffsets = {
		.offsets = offsets,
		.min = 0,
		.max = ARRAY_SIZE(offsets),
	};

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance)) {
		return MHAL_DEMUX_FAIL;
	}

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}


	return _mhal_demux_alp_reg16_write_for_array(
			   pBase,
			   &stOffsets,
			   u8Index,
			   u16Value);
}

static int _mhal_demux_alp_set_ip_source_addr_mask(
	demux_alp_instance_e eInstance, u8 u8Index, u16 u16Value)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u32 offsets[] = {
		REG_0140_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP1_0
		REG_0144_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP1_1
		REG_0148_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP1_2
		REG_014C_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP1_3
		REG_0150_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP1_4
		REG_0154_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP1_5
		REG_0158_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP1_6
		REG_015C_TSP_ALP, //REG_IP_SOURCE_ADDR_MMTP1_7
	};
	offsets_t stOffsets = {
		.offsets = offsets,
		.min = 0,
		.max = ARRAY_SIZE(offsets),
	};

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance)) {
		return MHAL_DEMUX_FAIL;
	}

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	return _mhal_demux_alp_reg16_write_for_array(
			   pBase,
			   &stOffsets,
			   u8Index,
			   u16Value);
}

static int _mhal_demux_alp_set_ip_destination_addr(
	demux_alp_instance_e eInstance, u8 u8Index, u16 u16Value)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u32 offsets[] = {
		REG_00E0_TSP_ALP, //REG_IP_DES_ADDR_MMTP_0
		REG_00E4_TSP_ALP, //REG_IP_DES_ADDR_MMTP_1
		REG_00E8_TSP_ALP, //REG_IP_DES_ADDR_MMTP_2
		REG_00EC_TSP_ALP, //REG_IP_DES_ADDR_MMTP_3
		REG_00F0_TSP_ALP, //REG_IP_DES_ADDR_MMTP_4
		REG_00F4_TSP_ALP, //REG_IP_DES_ADDR_MMTP_5
		REG_00F8_TSP_ALP, //REG_IP_DES_ADDR_MMTP_6
		REG_00FC_TSP_ALP, //REG_IP_DES_ADDR_MMTP_7
	};
	offsets_t stOffsets = {
		.offsets = offsets,
		.min = 0,
		.max = ARRAY_SIZE(offsets),
	};

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance)) {
		return MHAL_DEMUX_FAIL;
	}

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	return _mhal_demux_alp_reg16_write_for_array(
			   pBase,
			   &stOffsets,
			   u8Index,
			   u16Value);
}

static int _mhal_demux_alp_set_ip_destination_addr_mask(
	demux_alp_instance_e eInstance, u8 u8Index, u16 u16Value)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u32 offsets[] = {
		REG_0160_TSP_ALP, //REG_IP_DES_ADDR_MMTP1_0
		REG_0164_TSP_ALP, //REG_IP_DES_ADDR_MMTP1_1
		REG_0168_TSP_ALP, //REG_IP_DES_ADDR_MMTP1_2
		REG_016C_TSP_ALP, //REG_IP_DES_ADDR_MMTP1_3
		REG_0170_TSP_ALP, //REG_IP_DES_ADDR_MMTP1_4
		REG_0174_TSP_ALP, //REG_IP_DES_ADDR_MMTP1_5
		REG_0178_TSP_ALP, //REG_IP_DES_ADDR_MMTP1_6
		REG_017C_TSP_ALP, //REG_IP_DES_ADDR_MMTP1_7
	};
	offsets_t stOffsets = {
		.offsets = offsets,
		.min = 0,
		.max = ARRAY_SIZE(offsets),
	};

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance)) {
		return MHAL_DEMUX_FAIL;
	}

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	return _mhal_demux_alp_reg16_write_for_array(
			   pBase,
			   &stOffsets,
			   u8Index,
			   u16Value);
}

static int _mhal_demux_alp_set_udp_port(demux_alp_instance_e eInstance, u8 u8Index, u16 u16Value)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u32 offsets[] = {
		REG_0100_TSP_ALP, //REG_UDP_PORT_MMTP_0
		REG_0104_TSP_ALP, //REG_UDP_PORT_MMTP_1
	};
	offsets_t stOffsets = {
		.offsets = offsets,
		.min = 0,
		.max = ARRAY_SIZE(offsets),
	};

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance)) {
		return MHAL_DEMUX_FAIL;
	}

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(%d, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	switch (u8Index) {
	case DEMUX_ALP_UDP_PORT_SOURCE:
		// write 32bits
		_mhal_demux_alp_rewrite(MHAL_DEMUX_ALP_BASE(pBase, REG_0100_TSP_ALP));
		iRet = _mhal_demux_alp_reg16_write_for_array(
				   pBase,
				   &stOffsets,
				   u8Index,
				   u16Value);
		break;
	case DEMUX_ALP_UDP_PORT_DESTINATION:
		iRet = _mhal_demux_alp_reg16_write_for_array(
				   pBase,
				   &stOffsets,
				   u8Index,
				   u16Value);
		_mhal_demux_alp_rewrite(MHAL_DEMUX_ALP_BASE(pBase, REG_0104_TSP_ALP));
		break;
	default:
		iRet = MHAL_DEMUX_FAIL;
		break;
	}

	return iRet;
}

static int _mhal_demux_alp_set_udp_port_mask(
	demux_alp_instance_e eInstance, u8 u8Index, u16 u16Value)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u32 offsets[] = {
		REG_0108_TSP_ALP, //REG_UDP_PORT_MMTP1_0
		REG_010C_TSP_ALP, //REG_UDP_PORT_MMTP1_1
	};
	offsets_t stOffsets = {
		.offsets = offsets,
		.min = 0,
		.max = ARRAY_SIZE(offsets),
	};

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance)) {
		return MHAL_DEMUX_FAIL;
	}

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(%d, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	switch (u8Index) {
	case DEMUX_ALP_UDP_PORT_SOURCE:
		// write 32bits
		_mhal_demux_alp_rewrite(MHAL_DEMUX_ALP_BASE(pBase, REG_0108_TSP_ALP));
		iRet = _mhal_demux_alp_reg16_write_for_array(
				   pBase,
				   &stOffsets,
				   u8Index,
				   u16Value);
		break;
	case DEMUX_ALP_UDP_PORT_DESTINATION:
		// write 32bits
		iRet = _mhal_demux_alp_reg16_write_for_array(
				   pBase,
				   &stOffsets,
				   u8Index,
				   u16Value);
		_mhal_demux_alp_rewrite(MHAL_DEMUX_ALP_BASE(pBase, REG_010C_TSP_ALP));
		break;
	default:
		iRet = MHAL_DEMUX_FAIL;
		break;
	}

	return iRet;
}

static int _mhal_demux_alp_set_ip_source(demux_alp_instance_e eInstance, ip_addr_t *pstAddr)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	u8 u8Index = 0;

	if (pstAddr == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstAddr is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	_mhal_demux_alp_print_bytes(
		"uAddrs",
		pstAddr->uAddrs.u8Addrs,
		sizeof(pstAddr->uAddrs.u8Addrs));
	for (u8Index = 0; u8Index < DEMUX_ALP_IP_ADDR_MAX; u8Index++) {
		iRet = _mhal_demux_alp_set_ip_source_addr(
				   eInstance,
				   u8Index,
				   pstAddr->uAddrs.u16Addrs[u8Index]);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_ip_source_addr(0x%x, 0x%x, ...) is failed.\n",
				__func__,
				__LINE__,
				eInstance,
				u8Index);
			break;
		}

		_mhal_demux_alp_print_bytes(
			"uMasks",
			pstAddr->uMasks.u8Masks,
			sizeof(pstAddr->uMasks.u8Masks));
		iRet = _mhal_demux_alp_set_ip_source_addr_mask(
				   eInstance,
				   u8Index,
				   pstAddr->uMasks.u16Masks[u8Index]);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_ip_source_addr_mask(0x%x, 0x%x, ...) is failed.\n",
				__func__,
				__LINE__,
				eInstance,
				u8Index);
			break;
		}
	}

	return iRet;
}

static int _mhal_demux_alp_set_ip_destination(demux_alp_instance_e eInstance, ip_addr_t *pstAddr)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	u8 u8Index = 0;

	if (pstAddr == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstAddr is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	_mhal_demux_alp_print_bytes(
		"uAddrs",
		pstAddr->uAddrs.u8Addrs,
		sizeof(pstAddr->uAddrs.u8Addrs));
	for (u8Index = 0; u8Index < DEMUX_ALP_IP_ADDR_MAX; u8Index++) {
		iRet = _mhal_demux_alp_set_ip_destination_addr(
				   eInstance,
				   u8Index,
				   pstAddr->uAddrs.u16Addrs[u8Index]);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_ip_destination_addr(0x%x, 0x%x, ...) is failed.\n",
				__func__,
				__LINE__,
				eInstance,
				u8Index);
			break;
		}

		_mhal_demux_alp_print_bytes(
			"uMasks",
			pstAddr->uMasks.u8Masks,
			sizeof(pstAddr->uMasks.u8Masks));
		iRet = _mhal_demux_alp_set_ip_destination_addr_mask(
				   eInstance,
				   u8Index,
				   pstAddr->uMasks.u16Masks[u8Index]);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_ip_destination_addr_mask(0x%x, 0x%x, ...) is failed.\n",
				__func__,
				__LINE__,
				eInstance,
				u8Index);
			break;
		}
	}

	return iRet;
}

static int _mhal_demux_alp_set_udp_source_port(demux_alp_instance_e eInstance, udp_port_t *pstPort)
{
	int iRet = MHAL_DEMUX_SUCCESS;

	if (pstPort == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstPort is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	do {
		_mhal_demux_alp_print_bytes(
			"uPort",
			pstPort->uPort.u8Ports,
			sizeof(pstPort->uPort.u8Ports));
		iRet = _mhal_demux_alp_set_udp_port(
				   eInstance,
				   DEMUX_ALP_UDP_PORT_SOURCE,
				   pstPort->uPort.u16Port);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_udp_port(%x, DEMUX_ALP_UDP_PORT_SOURCE, 0x%x) is failed.\n",
				__func__,
				__LINE__,
				eInstance,
				pstPort->uPort.u16Port);
			break;
		}

		_mhal_demux_alp_print_bytes(
			"uMask",
			pstPort->uMask.u8Masks,
			sizeof(pstPort->uMask.u8Masks));
		iRet = _mhal_demux_alp_set_udp_port_mask(
				   eInstance,
				   DEMUX_ALP_UDP_PORT_SOURCE,
				   pstPort->uMask.u16Mask);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_udp_port_mask(0x%x, DEMUX_ALP_UDP_PORT_SOURCE, 0x%x) is failed.\n",
				__func__,
				__LINE__,
				eInstance,
				pstPort->uMask.u16Mask);
			break;
		}
	} while (0);

	return iRet;
}

static int _mhal_demux_alp_set_udp_destination_port(
	demux_alp_instance_e eInstance, udp_port_t *pstPort)
{
	int iRet = MHAL_DEMUX_SUCCESS;

	if (pstPort == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstPort is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	do {
		_mhal_demux_alp_print_bytes(
			"uPort",
			pstPort->uPort.u8Ports,
			sizeof(pstPort->uPort.u8Ports));
		iRet = _mhal_demux_alp_set_udp_port(
				   eInstance,
				   DEMUX_ALP_UDP_PORT_DESTINATION,
				   pstPort->uPort.u16Port);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_udp_port(0x%x, DEMUX_ALP_UDP_PORT_DESTINATION, 0x%x) is failed.\n",
				__func__,
				__LINE__,
				eInstance,
				pstPort->uPort.u16Port);
			break;
		}

		_mhal_demux_alp_print_bytes(
			"uMask",
			pstPort->uMask.u8Masks,
			sizeof(pstPort->uMask.u8Masks));
		iRet = _mhal_demux_alp_set_udp_port_mask(
				   eInstance,
				   DEMUX_ALP_UDP_PORT_DESTINATION,
				   pstPort->uMask.u16Mask);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_udp_port_mask(0x%x, DEMUX_ALP_UDP_PORT_DESTINATION, 0x%x) is failed.\n",
				__func__,
				__LINE__,
				eInstance,
				pstPort->uMask.u16Mask);
			break;
		}
	} while (0);

	return iRet;
}

static int _mhal_demux_alp_set_plp_id(demux_alp_instance_e eInstance, u8 u8PlpId)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u16 u16Value = (u16)u8PlpId;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(%d, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	// write 32bits
	_mhal_demux_alp_rewrite(MHAL_DEMUX_ALP_BASE(pBase, REG_01A8_TSP_ALP));
	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01AC_TSP_ALP),
		u16Value,
		REG_PLP_ID);

	return iRet;
}

static int _mhal_demux_alp_enable_plp(demux_alp_instance_e eInstance, bool bIsPlp)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(%d, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	// write 32bits
	_mhal_demux_alp_rewrite(MHAL_DEMUX_ALP_BASE(pBase, REG_01A8_TSP_ALP));
	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01AC_TSP_ALP),
		TRUE_TO_1(bIsPlp),
		REG_PLP_MASK);

	return iRet;
}

static int _mhal_demux_alp_set_single_plp_mode(demux_alp_instance_e eInstance, bool bSinglePlpMode)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(%d, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	// write 32bits
	_mhal_demux_alp_rewrite(MHAL_DEMUX_ALP_BASE(pBase, REG_01A0_TSP_ALP));
	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01A4_TSP_ALP),
		TRUE_TO_1(bSinglePlpMode),
		REG_SINGLE_PLP_MODE);

	return iRet;
}

static int _mhal_demux_alp_set_plp(demux_alp_instance_e eInstance, demux_alp_plp_t *pstPlp)
{
	int iRet = MHAL_DEMUX_SUCCESS;

	if (pstPlp == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstPlp is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	do {
		if (pstPlp->bSinglePlpMode) {
			iRet = _mhal_demux_alp_set_single_plp_mode(
					eInstance,
					pstPlp->bSinglePlpMode);
			if (iRet != MHAL_DEMUX_SUCCESS) {
				MHAL_DEMUX_ERR(
					"[%s][%d] _mhal_demux_alp_set_single_plp_mode(0x%x, ...) is failed.\n",
					__func__,
					__LINE__,
					(unsigned int) eInstance);
				break;
			}
		} else {
			iRet = _mhal_demux_alp_enable_plp(eInstance, pstPlp->bIsPlp);
			if (iRet != MHAL_DEMUX_SUCCESS) {
				MHAL_DEMUX_ERR(
					"[%s][%d] _mhal_demux_alp_enable_plp(0x%x, ...) is failed.\n",
					__func__,
					__LINE__,
					(unsigned int) eInstance);
				break;
			}

			_mhal_demux_alp_print_bytes(
				"u8PlpId",
				&pstPlp->u8PlpId,
				sizeof(pstPlp->u8PlpId));
			iRet = _mhal_demux_alp_set_plp_id(eInstance, pstPlp->u8PlpId);
			if (iRet != MHAL_DEMUX_SUCCESS) {
				MHAL_DEMUX_ERR(
					"[%s][%d] _mhal_demux_alp_set_plp_id(0x%x, ...) is failed.\n",
					__func__,
					__LINE__,
					eInstance);
				break;
			}
		}
	} while (0);

	return iRet;
}

static int _mhal_demux_alp_set_sid(demux_alp_instance_e eInstance, demux_alp_sid_t *pstSid)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (pstSid == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstSid is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	_mhal_demux_alp_print_bytes("Sid", &pstSid->u8Sid, sizeof(pstSid->u8Sid));

	// write 32bits
	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01A8_TSP_ALP),
		(u32)pstSid->u8Sid,
		REG_SID);
	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01AC_TSP_ALP),
		TRUE_TO_1(pstSid->bIsSid),
		REG_SID_FLAG);

	return iRet;
}

static int _mhal_demux_alp_set_cid(demux_alp_instance_e eInstance, demux_alp_cid_t *pstCid)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (pstCid == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstCid is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	_mhal_demux_alp_print_bytes("Cid", &pstCid->u8Cid, sizeof(pstCid->u8Cid));

	// write 32bits
	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01A8_TSP_ALP),
		(u32)pstCid->u8Cid,
		REG_CID);
	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01AC_TSP_ALP),
		TRUE_TO_1(pstCid->bIsCid),
		REG_COMP_FLAG);

	return iRet;
}

static int _mhal_demux_alp_set_filter_id(demux_alp_instance_e eInstance, u8 u8FilterId)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	// write 32bits
	_mhal_demux_alp_rewrite(MHAL_DEMUX_ALP_BASE(pBase, REG_01A8_TSP_ALP));
	vIO32WriteFld(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01AC_TSP_ALP),
		(u32)u8FilterId,
		REG_FILTER_ID);

	return iRet;
}

static int _mhal_demux_alp_apply_filter(demux_alp_instance_e eInstance, s8 s8Index)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;
	// TODO: CID for 24
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			0,
			DEMUX_ALP_IP_FILTER_MAX - 1,
			s8Index)) {
		return MHAL_DEMUX_FAIL;
	}

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	// REG_MTK_ALP_I_TOGGLE: 0->1->0
	// write 32 bits
	vIO32WriteFldMulti(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01B0_TSP_ALP),
		2,
		(u16)s8Index,
		REG_MTK_ALP_I,
		ENABLE,
		REG_MTK_ALP_I_TOGGLE);
	_mhal_demux_alp_rewrite(MHAL_DEMUX_ALP_BASE(pBase, REG_01B4_TSP_ALP));

	mdelay(TOGGLE_TIME);

	// write 32 bits
	vIO32WriteFldMulti(
		MHAL_DEMUX_ALP_BASE(pBase, REG_01B0_TSP_ALP),
		2,
		(u16)s8Index,
		REG_MTK_ALP_I,
		DISABLE,
		REG_MTK_ALP_I_TOGGLE);
	_mhal_demux_alp_rewrite(MHAL_DEMUX_ALP_BASE(pBase, REG_01B4_TSP_ALP));

	return iRet;
}

static int _mhal_demux_alp_enable_filter(demux_alp_instance_e eInstance, u8 u8Index, bool bEnable)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;
	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			0,
			DEMUX_ALP_IP_FILTER_MAX - 1,
			u8Index))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	iRet = _mhal_demux_alp_reg32_enable(
			   MHAL_DEMUX_ALP_BASE(pBase, REG_01B8_TSP_ALP),
			   u8Index,
			   bEnable);

	return iRet;
}

//-------------------------------------------------------------------------------------------------
//  Public Functions
//-------------------------------------------------------------------------------------------------
int mhal_demux_alp_init(demux_alp_instance_e eInstance)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	demux_alp_key_words_t stKeyWords = {0};

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	// TODO:
	_mhal_demux_alp_set_reset_n_in(eInstance, 0x7);

	// Move to mdrv_demux_tsio_set_input_src
	// mhal_demux_alp_set_path(eInstance, DEMUX_ALP_PATH_TYPE_LIVE_IN???);

	// Move to mdrv_demux_tsio_set_input_src
	//mhal_demux_alp_set_path(eInstance, DEMUX_ALP_PATH_TYPE_MTK_ALP_TOP_FROM_TSIF_ALP);

	// Move to mdrv_demux_pvr_set_record_cfg
	//mhal_demux_alp_set_path(eInstance, DEMUX_ALP_PATH_TYPE_FIFO_BEFORE_PVR_FROM_MTK_ALP_TOP);

	// Move to mdrv_demux_pvr_set_record_cfg
	//mhal_demux_alp_set_path(eInstance, DEMUX_ALP_PATH_TYPE_ALP_OUT_FIFO_FROM_FIFO_BEFORE_PVR);

	// TODO:
	_mhal_demux_alp_serial_framer_init(eInstance);

	// TODO:
	memset(&stKeyWords, 0, sizeof(demux_alp_key_words_t));
	stKeyWords.eKeyWordType = DEMUX_ALP_KEY_WORD_TYPE_KEY_WORD_1B_TIMESTAMP_4B;
	stKeyWords.u8keyWords[0] = MHAL_DEMUX_ALP_KEY_WORD_0_DEFAULT;
	mhal_demux_alp_set_key_words(eInstance, &stKeyWords);

	return iRet;
}

int mhal_demux_alp_exit(demux_alp_instance_e eInstance)
{
	int iRet = MHAL_DEMUX_SUCCESS;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	return iRet;
}

demux_alp_instance_e mhal_demux_alp_tsio_path_2_alp_instance(int path_id)
{
	demux_alp_instance_e alp_instance = DEMUX_ALP_INSTANCE_NULL;

	switch (path_id) {
	case TS_ALP_0:
		alp_instance = DEMUX_ALP_INSTANCE_0;
		break;
	case TS_ALP_FI:
		alp_instance = DEMUX_ALP_INSTANCE_1;
		break;
	default:
		MHAL_DEMUX_DEBUG(
			"[%s][%d] path_id(0x%x) is NULL.\n",
			__func__,
			__LINE__,
			path_id);
		break;
	}

	return alp_instance;
}

int mhal_demux_alp_set_path(demux_alp_instance_e eInstance, demux_alp_path_type_e ePathType)
{
	int iRet = MHAL_DEMUX_SUCCESS;

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_INSTANCE_MIN,
			DEMUX_ALP_INSTANCE_MAX - 1,
			eInstance))
		return MHAL_DEMUX_FAIL;

	MHAL_DEMUX_DEBUG(
		"[%s][%d] ePathType = 0x%x.\n",
		__func__,
		__LINE__,
		ePathType);

	switch (ePathType) {
	case DEMUX_ALP_PATH_TYPE_LIVE_IN_MIN ... DEMUX_ALP_PATH_TYPE_LIVE_IN_MAX:
		iRet = _mhal_demux_alp_set_path_for_live_in(eInstance, ePathType);
		break;
	case DEMUX_ALP_PATH_TYPE_FILEIN_MIN ... DEMUX_ALP_PATH_TYPE_FILEIN_MAX:
		iRet = _mhal_demux_alp_set_path_for_filein(eInstance, ePathType);
		break;
	case DEMUX_ALP_PATH_TYPE_MTK_ALP_TOP_MIN ... DEMUX_ALP_PATH_TYPE_MTK_ALP_TOP_MAX:
		iRet = _mhal_demux_alp_set_path_for_mtk_alp_top(eInstance, ePathType);
		break;
	case DEMUX_ALP_PATH_TYPE_FIFO_BEFORE_PVR_MIN ... DEMUX_ALP_PATH_TYPE_FIFO_BEFORE_PVR_MAX:
		iRet = _mhal_demux_alp_set_path_for_fifo_before_pvr(eInstance, ePathType);
		break;
	case DEMUX_ALP_PATH_TYPE_ALP_OUT_FIFO_MIN ... DEMUX_ALP_PATH_TYPE_ALP_OUT_FIFO_MAX:
		iRet = _mhal_demux_alp_set_path_for_alp_out_fifo(eInstance, ePathType);
		break;
	default:
		MHAL_DEMUX_ERR(
			"[%s][%d] ePathType(0x%x) is not supported.\n",
			__func__,
			__LINE__,
			ePathType);
		iRet = MHAL_DEMUX_FAIL;
		break;
	}

	return iRet;
}

int mhal_demux_alp_set_key_words(demux_alp_instance_e eInstance, demux_alp_key_words_t *pstKeyWords)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	REG16 __iomem *pBase = NULL;
	u16 u16Value = REG_INSERT_KEY_WORD_SEL_NO_INSERT;
	u8 u6KeyWordCount = 0;
	u8 u8Index = 0;

	if (pstKeyWords == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstKeyWords is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}

	if (MHAL_DEMUX_ALP_CHECK_RANGE(
			DEMUX_ALP_KEY_WORD_TYPE_MIN,
			DEMUX_ALP_KEY_WORD_TYPE_MAX - 1,
			pstKeyWords->eKeyWordType))
		return MHAL_DEMUX_FAIL;

	iRet = _mhal_demux_alp_getBase(eInstance, &pBase);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_getBase(0x%x, ...) is failed.\n",
			__func__,
			__LINE__,
			eInstance);

		return MHAL_DEMUX_FAIL;
	}

	_mhal_demux_alp_debug_change(
		eInstance,
		&_stDebugChanges[MHAL_DEMUX_ALP_DEBUG_CHANGE_FOR_KEY_WORD],
		pstKeyWords);

	switch (pstKeyWords->eKeyWordType) {
	case DEMUX_ALP_KEY_WORD_TYPE_KEY_WORD_1B_TIMESTAMP_4B:
		u16Value = REG_INSERT_KEY_WORD_SEL_KEY_WORD_1B_TIMESTAMP_4B;
		u6KeyWordCount = 1;
		break;
	case DEMUX_ALP_KEY_WORD_TYPE_KEY_WORD_4B_TIMESTAMP_4B:
		u16Value = REG_INSERT_KEY_WORD_SEL_KEY_WORD_4B_TIMESTAMP_4B;
		u6KeyWordCount = 4;
		break;
	case DEMUX_ALP_KEY_WORD_TYPE_KEY_WORD_4B:
		u16Value = REG_INSERT_KEY_WORD_SEL_KEY_WORD_4B;
		u6KeyWordCount = 4;
		break;
	case DEMUX_ALP_KEY_WORD_TYPE_TIMESTAMP_4B:
		u16Value = REG_INSERT_KEY_WORD_SEL_TIMESTAMP_4B;
		u6KeyWordCount = 0;
		break;
	default:
		u16Value = REG_INSERT_KEY_WORD_SEL_NO_INSERT;
		MHAL_DEMUX_WARN("[%s][%d] no key word is inserted.\n",
			__func__,
			__LINE__);
		break;
	}

	if (iRet == MHAL_DEMUX_SUCCESS) {
		do {
			vIO32WriteFld(
				MHAL_DEMUX_ALP_BASE(pBase, REG_006C_TSP_ALP),
				u16Value,
				REG_INSERT_KEY_WORD_SEL);

			_mhal_demux_alp_print_bytes(
				"u8keyWords",
				pstKeyWords->u8keyWords,
				sizeof(pstKeyWords->u8keyWords));
			for (u8Index = 0; u8Index < u6KeyWordCount; u8Index++) {
				iRet = _mhal_demux_alp_set_key_word(
						eInstance,
						u8Index,
						pstKeyWords->u8keyWords[u8Index]);
				if (iRet != MHAL_DEMUX_SUCCESS) {
					MHAL_DEMUX_ERR(
						"[%s][%d] _mhal_demux_alp_set_key_word(0x%x, ...) is failed.\n",
						__func__,
						__LINE__,
						u8Index);
					break;
				}
			}

			if (iRet != MHAL_DEMUX_SUCCESS)
				break;

			iRet = _mhal_demux_alp_enable_sideband(
					eInstance,
					pstKeyWords->bSidebandEnable);
		} while (0);
	}

	return iRet;
}

int mhal_demux_alp_get_filter(demux_alp_instance_e eInstance, demux_alp_filter_t *pstFilter)
{
	demux_alp_filter_t *pstFilterOld = _stFilter[eInstance];

	if (pstFilter == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstFilter is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}

	memcpy(pstFilter, &pstFilterOld[pstFilter->s8Index], sizeof(demux_alp_filter_t));

	return MHAL_DEMUX_SUCCESS;
}

int mhal_demux_alp_clear_filter(demux_alp_instance_e eInstance, demux_alp_filter_t *pstFilter)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	demux_alp_filter_t stAlpFilterNull = {0};

	if (pstFilter == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstFilter is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}

	_mhal_demux_alp_debug_change(
		eInstance,
		&_stDebugChanges[MHAL_DEMUX_ALP_DEBUG_CHANGE_FOR_FILTER],
		&stAlpFilterNull);

	iRet = _mhal_demux_alp_enable_filter(eInstance, pstFilter->s8Index, false);
	if (iRet != MHAL_DEMUX_SUCCESS) {
		MHAL_DEMUX_ERR(
			"[%s][%d] _mhal_demux_alp_enable_filter(%d) is failed.\n",
			__func__,
			__LINE__,
			(int) pstFilter->s8Index);
	}

	return iRet;
}

int mhal_demux_alp_set_filter(demux_alp_instance_e eInstance, demux_alp_filter_t *pstFilter)
{
	int iRet = MHAL_DEMUX_SUCCESS;
	demux_alp_filter_t *pstFilterOld = _stFilter[eInstance];

	if (pstFilter == NULL) {
		MHAL_DEMUX_ERR(
			"[%s][%d] pstFilter is NULL.\n",
			__func__,
			__LINE__);
		return MHAL_DEMUX_FAIL;
	}

	_mhal_demux_alp_debug_change(
		eInstance,
		&_stDebugChanges[MHAL_DEMUX_ALP_DEBUG_CHANGE_FOR_FILTER],
		pstFilter);

	memcpy(&pstFilterOld[pstFilter->s8Index], pstFilter, sizeof(demux_alp_filter_t));

	do {
		iRet = _mhal_demux_alp_set_ip_source(eInstance, &pstFilter->stSrcAddr);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_ip_source(...) is failed.\n",
				__func__,
				__LINE__);
			break;
		}

		iRet = _mhal_demux_alp_set_ip_destination(eInstance, &pstFilter->stDesAddr);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_ip_destination(...) is failed.\n",
				__func__,
				__LINE__);
			break;
		}

		iRet = _mhal_demux_alp_set_udp_source_port(eInstance, &pstFilter->stSrcPort);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_udp_source_port(...) is failed.\n",
				__func__,
				__LINE__);
			break;
		}

		iRet = _mhal_demux_alp_set_udp_destination_port(eInstance, &pstFilter->stDesPort);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_udp_destination_port(...) is failed.\n",
				__func__,
				__LINE__);
			break;
		}

		iRet = _mhal_demux_alp_set_plp(eInstance, &pstFilter->stPlp);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_plp(...) is failed.\n",
				__func__,
				__LINE__);
			break;
		}

		iRet = _mhal_demux_alp_set_sid(eInstance, &pstFilter->stSid);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_sid(...) is failed.\n",
				__func__,
				__LINE__);
			break;
		}

		iRet = _mhal_demux_alp_set_cid(eInstance, &pstFilter->stCid);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_cid(...) is failed.\n",
				__func__,
				__LINE__);
			break;
		}

		iRet = _mhal_demux_alp_set_filter_id(eInstance, pstFilter->u8FilterId);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_set_filter_id(...) is failed.\n",
				__func__,
				__LINE__);
			break;
		}

		_mhal_demux_alp_print_alp_filter_regs();

		iRet = _mhal_demux_alp_apply_filter(eInstance, pstFilter->s8Index);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_apply_filter(%d) is failed.\n",
				__func__,
				__LINE__,
				(int) pstFilter->s8Index);
			break;
		}

		iRet = _mhal_demux_alp_enable_filter(eInstance, pstFilter->s8Index, true);
		if (iRet != MHAL_DEMUX_SUCCESS) {
			MHAL_DEMUX_ERR(
				"[%s][%d] _mhal_demux_alp_enable_filter(%d) is failed.\n",
				__func__,
				__LINE__,
				(int) pstFilter->s8Index);
			break;
		}

		_mhal_demux_alp_print_alp_filter_enable_regs();
	} while (0);

	return iRet;
}
