static int mpq_tspp_remove_accept_all_filter(int channel_id,
				enum tspp_source source)
{
	struct tspp_filter tspp_filter;
	int tsif = TSPP_GET_TSIF_NUM(channel_id);
	int ret;

	MPQ_DVB_DBG_PRINT("%s: executed, channel id = %d, source = %d\n",
		__func__, channel_id, source);

	if (mpq_dmx_tspp_info.tsif[tsif].accept_all_filter_exists_flag == 0) {
		MPQ_DVB_DBG_PRINT("%s: accept all filter doesn't exist\n",
				__func__);
		return 0;
	}

	tspp_filter.priority = TSPP_LAST_HW_FILTER_INDEX;

	ret = tspp_remove_filter(0, channel_id, &tspp_filter);
	if (!ret) {
		mpq_dmx_tspp_info.tsif[tsif].accept_all_filter_exists_flag = 0;
		MPQ_DVB_DBG_PRINT(
			"%s: accept all filter removed successfully\n",
			__func__);
	}

	return ret;
}
static int mpq_tspp_add_accept_all_filter(int channel_id,
				enum tspp_source source)
{
	struct tspp_filter tspp_filter;
	int tsif = TSPP_GET_TSIF_NUM(channel_id);
	int ret;

	MPQ_DVB_DBG_PRINT("%s: executed, channel id = %d, source = %d\n",
		__func__, channel_id, source);

	if (mpq_dmx_tspp_info.tsif[tsif].accept_all_filter_exists_flag) {
		MPQ_DVB_DBG_PRINT("%s: accept all filter already exists\n",
				__func__);
		return 0;
	}

	
	tspp_filter.priority = TSPP_LAST_HW_FILTER_INDEX;
	
	tspp_filter.pid = 0;
	tspp_filter.mask = 0;
	tspp_filter.mode = TSPP_MODE_RAW;
	tspp_filter.source = source;
	tspp_filter.decrypt = 0;

	ret = tspp_add_filter(0, channel_id, &tspp_filter);
	if (!ret) {
		mpq_dmx_tspp_info.tsif[tsif].accept_all_filter_exists_flag = 1;
		MPQ_DVB_DBG_PRINT(
				"%s: accept all filter added successfully\n",
				__func__);
	}

	return ret;
}
static void tspp_mem_free(int channel_id, u32 size,
			void *virt_base, phys_addr_t phys_base, void *user)
{
	int i = TSPP_GET_TSIF_NUM(channel_id);

	if (mpq_dmx_tspp_info.tsif[i].buff_index > 0)
		mpq_dmx_tspp_info.tsif[i].buff_index--;
}
static int mpq_tspp_add_all_user_filters(int channel_id,
				enum tspp_source source)
{
	struct tspp_filter tspp_filter;
	int tsif = TSPP_GET_TSIF_NUM(channel_id);
	int slot;
	u16 added_count = 0;
	u16 total_filters_count = 0;

	MPQ_DVB_DBG_PRINT("%s: executed\n", __func__);

	tspp_filter.mode = TSPP_MODE_RAW;
	tspp_filter.source = source;
	tspp_filter.decrypt = 0;

	for (slot = 0; slot < TSPP_MAX_PID_FILTER_NUM; slot++) {
		if (mpq_dmx_tspp_info.tsif[tsif].filters[slot].pid == -1)
			continue;

		total_filters_count++;

		if (added_count > TSPP_MAX_HW_PID_FILTER_NUM)
			continue;

		tspp_filter.priority = mpq_tspp_allocate_hw_filter_index(tsif);

		if (mpq_dmx_tspp_info.tsif[tsif].filters[slot].pid ==
				TSPP_PASS_THROUGH_PID) {
			
			tspp_filter.pid = 0;
			tspp_filter.mask = 0;
		} else {
			tspp_filter.pid =
				mpq_dmx_tspp_info.tsif[tsif].filters[slot].pid;
			tspp_filter.mask = TSPP_PID_MASK;
		}

		MPQ_DVB_DBG_PRINT(
			"%s: adding HW filter, PID = %d, mask = 0x%X, index = %d\n",
				__func__, tspp_filter.pid, tspp_filter.mask,
				tspp_filter.priority);

		if (!tspp_add_filter(0, channel_id, &tspp_filter)) {
			mpq_dmx_tspp_info.tsif[tsif].filters[slot].hw_index =
				tspp_filter.priority;
			added_count++;
		} else {
			MPQ_DVB_ERR_PRINT("%s: tspp_add_filter failed\n",
						__func__);
		}
	}

	if ((added_count != TSPP_MAX_HW_PID_FILTER_NUM) ||
		(added_count != total_filters_count))
		return -EINVAL;

	return 0;
}
static int mpq_tspp_add_null_blocking_filters(int channel_id,
				enum tspp_source source)
{
	struct tspp_filter tspp_filter;
	int ret = 0;
	int i, j;
	u16 full_pid_mask = 0x1FFF;
	u8 mask_shift;
	u8 pid_shift;
	int tsif = TSPP_GET_TSIF_NUM(channel_id);

	MPQ_DVB_DBG_PRINT("%s: executed, channel id = %d, source = %d\n",
		__func__, channel_id, source);


	tspp_filter.mode = TSPP_MODE_RAW;
	tspp_filter.source = source;
	tspp_filter.decrypt = 0;

	for (i = 0; i < TSPP_BLOCK_NULLS_FILTERS_NUM; i++) {
		tspp_filter.priority = mpq_tspp_allocate_hw_filter_index(tsif);
		if (tspp_filter.priority != i) {
			MPQ_DVB_ERR_PRINT(
				"%s: got unexpected HW index %d, expected %d\n",
				__func__, tspp_filter.priority, i);
			ret = -1;
			break;
		}
		mask_shift = (TSPP_BLOCK_NULLS_FILTERS_NUM - 1 - i);
		pid_shift = (TSPP_BLOCK_NULLS_FILTERS_NUM - i);
		tspp_filter.mask =
			((full_pid_mask >> mask_shift) << mask_shift);
		tspp_filter.pid = ((full_pid_mask >> pid_shift) << pid_shift);

		if (tspp_add_filter(0, channel_id, &tspp_filter)) {
			ret = -1;
			break;
		}
	}

	if (ret) {
		
		for (j = 0; j < i; j++) {
			tspp_filter.priority = j;
			mpq_tspp_release_hw_filter_index(tsif, j);
			tspp_remove_filter(0, channel_id, &tspp_filter);
		}
	} else {
		MPQ_DVB_DBG_PRINT(
			"%s: NULL blocking filters added successfully\n",
			__func__);
	}

	return ret;
}
static void tspp_mem_free(int channel_id, u32 size,
			void *virt_base, u32 phys_base, void *user)
{
	int i = TSPP_GET_TSIF_NUM(channel_id);

	/*
	 * actual buffer heap free is done in mpq_dmx_tspp_plugin_exit().
	 * we update index here, so if this function is called repetitively
	 * for all the buffers, then afterwards tspp_mem_allocator()
	 * can be called again.
	 * Note: it would be incorrect to call tspp_mem_allocator()
	 * a few times, then call tspp_mem_free(), then call
	 * tspp_mem_allocator() again.
	 */
	if (mpq_dmx_tspp_info.tsif[i].buff_index > 0)
		mpq_dmx_tspp_info.tsif[i].buff_index--;
}
static void *tspp_mem_allocator(int channel_id, u32 size,
				u32 *phys_base, void *user)
{
	void *virt_addr = NULL;
	int i = TSPP_GET_TSIF_NUM(channel_id);

	if (mpq_dmx_tspp_info.tsif[i].buff_index ==
		mpq_dmx_tspp_info.tsif[i].buffer_count)
		return NULL;

	virt_addr =
		(mpq_dmx_tspp_info.tsif[i].ch_mem_heap_virt_base +
		(mpq_dmx_tspp_info.tsif[i].buff_index * size));

	*phys_base =
		(mpq_dmx_tspp_info.tsif[i].ch_mem_heap_phys_base +
		(mpq_dmx_tspp_info.tsif[i].buff_index * size));

	mpq_dmx_tspp_info.tsif[i].buff_index++;

	return virt_addr;
}
static int mpq_tspp_remove_all_user_filters(int channel_id,
				enum tspp_source source)
{
	struct tspp_filter tspp_filter;
	int ret = 0;
	int tsif = TSPP_GET_TSIF_NUM(channel_id);
	int i;

	MPQ_DVB_DBG_PRINT("%s: executed\n", __func__);

	for (i = 0; i < TSPP_MAX_HW_PID_FILTER_NUM; i++) {
		tspp_filter.priority = i;
		MPQ_DVB_DBG_PRINT("%s: Removing HW filter %d\n",
			__func__, tspp_filter.priority);
		if (tspp_remove_filter(0, channel_id, &tspp_filter))
			ret = -1;

		mpq_tspp_release_hw_filter_index(tsif, i);
		mpq_dmx_tspp_info.tsif[tsif].filters[i].hw_index = -1;
	}

	return ret;
}
static int mpq_tspp_remove_null_blocking_filters(int channel_id,
				enum tspp_source source)
{
	struct tspp_filter tspp_filter;
	int tsif = TSPP_GET_TSIF_NUM(channel_id);
	int ret = 0;
	int i;

	MPQ_DVB_DBG_PRINT("%s: executed, channel id = %d, source = %d\n",
		__func__, channel_id, source);

	for (i = 0; i < TSPP_BLOCK_NULLS_FILTERS_NUM; i++) {
		tspp_filter.priority = i;
		if (tspp_remove_filter(0, channel_id, &tspp_filter)) {
			MPQ_DVB_ERR_PRINT("%s: failed to remove filter %d\n",
				__func__, i);
			ret = -1;
		}

		mpq_tspp_release_hw_filter_index(tsif, i);
	}

	return ret;
}