// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2020 MediaTek Inc.
 *
 */


#if (defined(CONFIG_MTK_IN_HOUSE_TEE_SUPPORT) || defined(CONFIG_OPTEE))
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/kobject.h>
#include <linux/platform_device.h>
#include <linux/atomic.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/byteorder/generic.h>
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/dma-mapping.h>
#include <linux/syscalls.h>
#include <linux/reboot.h>
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/completion.h>
#include <hdmitx.h>
#include <hdmictrl.h>

#include "tz_cross/trustzone.h"
#include "tz_cross/ta_test.h"
#include "tz_cross/ta_mem.h"
#include "kree/system.h"
#include "kree/mem.h"

#include "tz_cross/ta_hdmitx.h"
#include "hdmi_ca.h"
#include "hdmihdcp.h"

#include <linux/err.h>
#include <linux/tee_drv.h>
#define TEEC_PAYLOAD_REF_COUNT 4

#ifdef CONFIG_MTK_IN_HOUSE_TEE_SUPPORT

KREE_SESSION_HANDLE ca_hdmi_handle;
KREE_SESSION_HANDLE hdmitx_mem_session;

bool fgCaHDMICreate(void)
{
	int tz_ret = 0;

	tz_ret = KREE_CreateSession(TZ_TA_HDMI_UUID, &ca_hdmi_handle);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		/* Should provide strerror style error string in UREE. */
		TX_DEF_LOG("Create ca_hdmi_handle Error: %d\n", tz_ret);
		return false;
	}
	TX_DEF_LOG("Create ca_hdmi_handle ok: %d\n", tz_ret);

	tz_ret = KREE_CreateSession(TZ_TA_MEM_UUID, &hdmitx_mem_session);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]Create memory session error %d\n", tz_ret);
		return false;
	}
	TX_DEF_LOG("Create ca_hdmi_memory_handle ok: %d\n", tz_ret);

	return true;
}

bool fgCaHDMIClose(void)
{
	int tz_ret = 0;

	tz_ret = KREE_CloseSession(ca_hdmi_handle);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		/* Should provide strerror style error string in UREE. */
		TX_DEF_LOG("Close ca_hdmi_handle Error: %d\n", tz_ret);
		return false;
	}
	TX_DEF_LOG("Close ca_hdmi_handle ok: %d\n", tz_ret);

	tz_ret = KREE_CloseSession(hdmitx_mem_session);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("Close HDMITX memory session error %d\n", tz_ret);
		return false;
	}
	TX_DEF_LOG("Close ca_hdmi_memory_handle ok: %d\n", tz_ret);

	return true;
}

void vCaHDMIWriteReg(unsigned int u4addr, unsigned int u4data)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[2];

	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[CA]TEE ca_hdmi_handle=0\n");
		return;
	}

	param[0].value.a = u4addr & 0xFFF;
	param[0].value.b = 0;
	param[1].value.a = u4data;
	param[1].value.b = 0;

	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_WRITE_REG,
				     TZ_ParamTypes2(TZPT_VALUE_INPUT,
				     TZPT_VALUE_INPUT), param);

	if (tz_ret != TZ_RESULT_SUCCESS)
		TX_DEF_LOG("[CA] HDMI_TA_WRITE_REG err:%X\n", tz_ret);

}

void vCaHDMIWriteHDCPRST(unsigned int u4addr, unsigned int u4data)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[2];

	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[CA]TEE ca_hdmi_handle=0\n");
		return;
	}

	param[0].value.a = u4addr;
	param[0].value.b = 0;
	param[1].value.a = u4data;
	param[1].value.b = 0;

	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_HDCP_RST,
				     TZ_ParamTypes2(TZPT_VALUE_INPUT,
				     TZPT_VALUE_INPUT), param);

	if (tz_ret != TZ_RESULT_SUCCESS)
		TX_DEF_LOG("[CA] HDMI_TA_WRITE_REG err:%X\n", tz_ret);

}

void vCaHDMIWriteHdcpCtrl(unsigned int u4addr, unsigned int u4data)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[2];

	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[HDMI] TEE ca_hdmi_handle=0\n");
		return;
	}

	param[0].value.a = u4addr;
	param[0].value.b = 0;
	param[1].value.a = u4data;
	param[1].value.b = 0;

	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_WRITE_REG,
				     TZ_ParamTypes2(TZPT_VALUE_INPUT,
				     TZPT_VALUE_INPUT), param);

	if (tz_ret != TZ_RESULT_SUCCESS)
		TX_DEF_LOG("[CA]HDMI_TA_WRITE_REG err:%X\n", tz_ret);
}

bool fgCaHDMIInstallHdcpKey(unsigned char *pdata, unsigned int u4Len)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[2];

	KREE_SHAREDMEM_HANDLE hdmitx_shm_handle;
	struct KREE_SHAREDMEM_PARAM hdmitx_shm_param;

	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[CA] TEE ca_hdmi_handle=0\n");
		return false;
	}
	TX_DEF_LOG("[CA]%s,%d\n", __func__, u4Len);

	if (u4Len > HDCPKEY_LENGTH_DRM)
		return false;

	hdmitx_shm_param.buffer = pdata;
	hdmitx_shm_param.size = u4Len;

	tz_ret = KREE_RegisterSharedmem(hdmitx_mem_session,
		&hdmitx_shm_handle, &hdmitx_shm_param);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]KREE_RegisterSharedmem Error\n");
		return false;
	}

	param[0].memref.handle = (uint32_t) hdmitx_shm_handle;
	param[0].memref.offset = 0;
	param[0].memref.size = u4Len;

	param[1].value.a = u4Len;
	param[1].value.b = 0;

	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_INSTALL_HDCP_KEY,
				     TZ_ParamTypes2(TZPT_MEMREF_INPUT,
				     TZPT_VALUE_INPUT), param);

	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA] HDMI_TA_INSTALL_HDCP_KEY err:%X\n", tz_ret);

		tz_ret = KREE_UnregisterSharedmem(hdmitx_mem_session,
			hdmitx_shm_handle);
		if (tz_ret != TZ_RESULT_SUCCESS)
			TX_DEF_LOG("[CA]KREE_UnregisterSharedmem Error\n");
		return false;
	}

	tz_ret = KREE_UnregisterSharedmem(hdmitx_mem_session,
		hdmitx_shm_handle);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]KREE_UnregisterSharedmem Error\n");
		return false;
	}

	return true;
}

bool fgCaHDMIGetAKsv(unsigned char *pdata)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[1];
	unsigned char *ptr;
	unsigned char i;
	KREE_SHAREDMEM_HANDLE hdmitx_shm_handle;
	struct KREE_SHAREDMEM_PARAM hdmitx_shm_param;

	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[CA] TEE ca_hdmi_handle=0\n");
		return false;
	}

	ptr = kmalloc(HDCP_AKSV_COUNT, GFP_KERNEL);
	if (ptr == NULL) {
		TX_DEF_LOG("[CA] AKSV kmalloc failure\n");
		return false;
	}

	hdmitx_shm_param.buffer = ptr;
	hdmitx_shm_param.size = HDCP_AKSV_COUNT;
	tz_ret = KREE_RegisterSharedmem(hdmitx_mem_session,
		&hdmitx_shm_handle, &hdmitx_shm_param);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]KREE_RegisterSharedmem Error\n");
		return false;
	}

	param[0].memref.handle = (uint32_t) hdmitx_shm_handle;
	param[0].memref.offset = 0;
	param[0].memref.size = HDCP_AKSV_COUNT;
	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_GET_HDCP_AKSV,
			TZ_ParamTypes1(TZPT_MEMREF_OUTPUT), param);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]HDMI_TA_GET_HDCP_AKSV err:%X\n", tz_ret);

		tz_ret = KREE_UnregisterSharedmem(hdmitx_mem_session,
			hdmitx_shm_handle);
		if (tz_ret != TZ_RESULT_SUCCESS)
			TX_DEF_LOG("[CA]KREE_UnregisterSharedmem Error\n");
		kfree(ptr);
		return false;
	}

	tz_ret = KREE_UnregisterSharedmem(hdmitx_mem_session,
		hdmitx_shm_handle);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]KREE_UnregisterSharedmem Error\n");
		kfree(ptr);
		return false;
	}

	for (i = 0; i < HDCP_AKSV_COUNT; i++)
		pdata[i] = ptr[i];

	TX_DEF_LOG("[CA]hdcp aksv : %x %x %x %x %x\n",
		   pdata[0], pdata[1], pdata[2], pdata[3], pdata[4]);
	kfree(ptr);
	return true;

}

bool fgCaHDMIGetTAStatus(unsigned char *pdata)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[1];
	unsigned char *ptr;
	KREE_SHAREDMEM_HANDLE hdmitx_shm_handle;
	struct KREE_SHAREDMEM_PARAM hdmitx_shm_param;

	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[CA] TEE ca_hdmi_handle=0\n");
		return false;
	}

	ptr = kmalloc(2, GFP_KERNEL);
	if (ptr == NULL) {
		TX_DEF_LOG("[CA]%s\n", __func__);
		return false;
	}

	hdmitx_shm_param.buffer = ptr;
	hdmitx_shm_param.size = 2;
	tz_ret = KREE_RegisterSharedmem(hdmitx_mem_session,
		&hdmitx_shm_handle, &hdmitx_shm_param);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]KREE_RegisterSharedmem Error\n");
		return false;
	}

	param[0].memref.handle = (uint32_t) hdmitx_shm_handle;
	param[0].memref.offset = 0;
	param[0].memref.size = 2;
	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_READ_STATUS,
				     TZ_ParamTypes1(TZPT_MEMREF_OUTPUT), param);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]%s err:%X\n", __func__, tz_ret);

		tz_ret = KREE_UnregisterSharedmem(hdmitx_mem_session,
			hdmitx_shm_handle);
		if (tz_ret != TZ_RESULT_SUCCESS)
			TX_DEF_LOG("[CA]KREE_UnregisterSharedmem Error\n");
		kfree(ptr);
		return false;
	}

	tz_ret = KREE_UnregisterSharedmem(hdmitx_mem_session,
		hdmitx_shm_handle);
	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]KREE_UnregisterSharedmem Error\n");
		kfree(ptr);
		return false;
	}

	pdata[0] = ptr[0];
	pdata[1] = ptr[1];

	kfree(ptr);
	return true;
}

bool fgCaHDMILoadHDCPKey(void)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[1];

	TX_DEF_LOG("[CA] %s\n", __func__);
	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[CA] TEE ca_hdmi_handle=0\n");
		return false;
	}
	param[0].value.a = 0;
	param[0].value.b = 0;

	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_LOAD_HDCP_KEY,
				     TZ_ParamTypes1(TZPT_VALUE_INPUT), param);

	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA] HDMI_TA_LOAD_HDCP_KEY err:%X\n", tz_ret);
		return false;
	}
	return true;
}

bool fgCaHDMILoadROM(void)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[1];

	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[CA] TEE ca_hdmi_handle=0\n");
		return false;
	}

	param[0].value.a = 0;
	param[0].value.b = 0;

	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_LOAD_ROM,
				     TZ_ParamTypes1(TZPT_VALUE_INPUT), param);

	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]HDMI_TA_LOAD_ROM err:%X\n", tz_ret);
		return false;
	}
	return true;
}


bool fgCaHDMITestHDCPVersion(void)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[1];

	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[CA] TEE ca_hdmi_handle=0\n");
		return false;
	}

	param[0].value.a = 0;
	param[0].value.b = 0;

	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_TEST_HDCP_VERSION,
				     TZ_ParamTypes1(TZPT_VALUE_INPUT), param);

	if (tz_ret != TZ_RESULT_SUCCESS) {
		TX_DEF_LOG("[CA]HDMI_TA_TEST_HDCP_VERSION err:%X\n", tz_ret);
		return false;
	}
	return true;
}

void fgCaHDMISetTzLogLevel(unsigned int loglevel)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[2];

	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[HDMI] TEE ca_hdmi_handle=0\n");
		return;
	}

	param[0].value.a = loglevel;
	param[0].value.b = 0;

	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_SET_LOG_LEVEL,
				     TZ_ParamTypes1(TZPT_VALUE_INPUT), param);

	if (tz_ret != TZ_RESULT_SUCCESS)
		TX_DEF_LOG("[CA]HDMI_TA_SET_LOG_LEVEL err:%X\n", tz_ret);
}

void fgCaHDMISetSecureRegEntry(unsigned int Tx_entry,
	unsigned int Rx_entry)
{
	int tz_ret = 0;
	union MTEEC_PARAM param[2];

	if (ca_hdmi_handle == 0) {
		TX_DEF_LOG("[CA]TEE ca_hdmi_handle=0\n");
		return;
	}

	param[0].value.a = Tx_entry;
	param[0].value.b = 0;
	param[1].value.a = Rx_entry;
	param[1].value.b = 0;

	tz_ret = KREE_TeeServiceCall(ca_hdmi_handle, HDMI_TA_SECURE_REG_ENTRY,
				     TZ_ParamTypes2(TZPT_VALUE_INPUT,
				     TZPT_VALUE_INPUT), param);

	if (tz_ret != TZ_RESULT_SUCCESS)
		TX_DEF_LOG("[CA] HDMI_TA_SECURE_REG_ENTRY err:%X\n", tz_ret);
}

#else

static int hdmitx_optee_dev_match(
	struct tee_ioctl_version_data *t, const void *v)
{	if (t->impl_id == TEE_IMPL_ID_OPTEE)
		return 1;
	return 0;
}

struct tee_context *hdmitx_tee_ctx;
struct tee_ioctl_open_session_arg hdmitx_session_arg;
struct HDMI_GEN_PKT_T *hdmi_gen_pkt;
int hdmi_gen_pkt_id;

bool fgCaHDMICreate(void)
{
	int rc, ret;
	unsigned char hdmitx_uuid[] = {
		0xea, 0xf8, 0x00, 0xb0, 0xda, 0x1b, 0x11, 0xe2,
		0xa2, 0x8f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
	};
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	/* 0: open context */
	hdmitx_tee_ctx = tee_client_open_context(NULL,
		hdmitx_optee_dev_match, NULL, NULL);
	if (IS_ERR(hdmitx_tee_ctx)) {
		TX_DEF_LOG("[CA] open_context failed err %ld",
			PTR_ERR(hdmitx_tee_ctx));
		return false;
	}
	TX_DEF_LOG("[CA] open_context succeed! tee_ctx = %lx\n",
		(unsigned long)hdmitx_tee_ctx);

	/* 1: open session */
	memset(&hdmitx_session_arg, 0, sizeof(hdmitx_session_arg));
	hdmitx_session_arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	hdmitx_session_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
	memcpy(hdmitx_session_arg.uuid, hdmitx_uuid, sizeof(hdmitx_uuid));
	memset(params, 0, sizeof(params));
	rc = tee_client_open_session(hdmitx_tee_ctx,
			&hdmitx_session_arg, params);
	if (rc || hdmitx_session_arg.ret) {
		TX_DEF_LOG("open_session failed err %d, ret=%d",
			rc, hdmitx_session_arg.ret);
		goto close_context;
	}
	TX_DEF_LOG("[CA] open_session succeed! session = %lx\n",
		(unsigned long)hdmitx_session_arg.session);

	hdmi_gen_pkt = kmalloc(sizeof(struct HDMI_GEN_PKT_T), GFP_KERNEL);
	if (hdmi_gen_pkt == NULL) {
		TX_DEF_LOG("[CA]malloc hdmi_gen_pkt fail\n");
		goto close_context;
	}
	memset(hdmi_gen_pkt, 0, sizeof(struct HDMI_GEN_PKT_T));
	/* alloc shm for logbuf */
	ret = tee_client_register_shm(hdmitx_tee_ctx,
			(unsigned long)hdmi_gen_pkt,
			sizeof(struct HDMI_GEN_PKT_T),
			&hdmi_gen_pkt_id);

	return true;

close_context:
	/* 5: close context */
	tee_client_close_context(hdmitx_tee_ctx);
	return false;
}

bool fgCaHDMIClose(void)
{
	int rc;
	/* close session */
	rc = tee_client_close_session(hdmitx_tee_ctx,
		hdmitx_session_arg.session);
	if (rc != 0) {
		TX_DEF_LOG("[CA] close_session failed err %d", rc);
		return false;
	}
	return true;
}

void vCaHDMIWriteReg(unsigned int u4addr, unsigned int u4data)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	arg.func = HDMI_TA_WRITE_REG;

	/* cmd id */
	memset(params, 0, sizeof(params));
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = u4addr & 0xFFF;
	params[0].u.value.b = 0;
	params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[1].u.value.a = u4data;
	params[1].u.value.b = 0;

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc)
		TX_DEF_LOG("[CA] %s(): rc = %d\n", __func__, rc);
}

void vCaHDMISendGEN(enum HDMI_GEN_PACKET_HW_ENUM type,
	bool en, u8 *pkt)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	//arg.func = HDMI_TA_SEND_GEN;   //YulanRemove

	/* cmd id */
	memset(params, 0, sizeof(params));
	memset(hdmi_gen_pkt, 0, sizeof(struct HDMI_GEN_PKT_T));
	hdmi_gen_pkt->type = type;
	hdmi_gen_pkt->en = en;
	memcpy(&hdmi_gen_pkt->pkt[0], pkt, 32);
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = tee_shm_get_from_id(hdmitx_tee_ctx, hdmi_gen_pkt_id);
	params[0].u.memref.size = sizeof(struct HDMI_GEN_PKT_T);

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc)
		TX_DEF_LOG("[CA] %s(): rc = %d\n", __func__, rc);
}

void vCaHDMIWriteHDCPRST(unsigned int u4addr, unsigned int u4data)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	arg.func = HDMI_TA_HDCP_RST;

	/* cmd id */
	memset(params, 0, sizeof(params));
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = u4addr;
	params[0].u.value.b = 0;
	params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[1].u.value.a = u4data;
	params[1].u.value.b = 0;

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc)
		TX_DEF_LOG("[CA] %s(): rc = %d\n", __func__, rc);

}


void vCaHDMIWriteHdcpCtrl(unsigned int u4addr, unsigned int u4data)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	arg.func = HDMI_TA_WRITE_REG;

	/* cmd id */
	memset(params, 0, sizeof(params));
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = u4addr;
	params[0].u.value.b = 0;
	params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[1].u.value.a = u4data;
	params[1].u.value.b = 0;

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc)
		TX_DEF_LOG("[CA] %s(): rc = %d\n", __func__, rc);
}

bool fgCaHDMIInstallHdcpKey(unsigned char *pdata, unsigned int u4Len)
{
	TX_DEF_LOG("[CA] %s()\n", __func__);
	return true;

	/* HDMI service call KeyManager CA API in userspace,
	 * then KeyManager Ta deliver decrtpted hdcp key to
	 * HDMI Ta directly. Not use the obsoleted flow like:
	 * 1.HDMI service deliver encrypted key to
	 *   HDMI driver from userspace to kernel;
	 * 2.HDMI driver Ca deliver encrypted key to HDMI TA;
	 * 3.HDMI Ta decrypt the encrypted key.
	 */
}

bool fgCaHDMIGetAKsv(unsigned char *pdata)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	TX_DEF_LOG("[CA] %s()\n", __func__);

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return false;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	arg.func = HDMI_TA_GET_HDCP_AKSV;

	/* cmd id */
	memset(params, 0, sizeof(params));
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
	params[0].u.value.a = 0;
	params[0].u.value.b = 0;
	params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
	params[1].u.value.a = 0;
	params[1].u.value.b = 0;

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc) {
		TX_DEF_LOG("[CA] %s(): rc = %d\n", __func__, rc);
		return false;
	}
	pdata[0] = params[0].u.value.a & 0xff;
	pdata[1] = (params[0].u.value.a >> 8) & 0xff;
	pdata[2] = (params[0].u.value.a >> 16) & 0xff;
	pdata[3] = (params[0].u.value.a >> 24) & 0xff;
	pdata[4] = params[1].u.value.a & 0xff;
	TX_DEF_LOG("[CA]hdcp aksv : %x %x %x %x %x\n",
		   pdata[0], pdata[1], pdata[2], pdata[3], pdata[4]);

	if ((pdata[0] == 0) && (pdata[1] == 0) && (pdata[2] == 0)
		&& (pdata[3] == 0) && (pdata[4] == 0)) {
		TX_DEF_LOG("[CA]hdcp aksv : Invalid AKSV\n");
		return false;
	}

	return true;

}

bool fgCaHDMIGetTAStatus(unsigned char *pdata)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	TX_DEF_LOG("[CA] %s()\n", __func__);

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return false;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	arg.func = HDMI_TA_READ_STATUS;

	/* cmd id */
	memset(params, 0, sizeof(params));
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
	params[0].u.value.a = 0;
	params[0].u.value.b = 0;
	params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
	params[1].u.value.a = 0;
	params[1].u.value.b = 0;

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc) {
		TX_DEF_LOG("[CA] %s(): rc = %d\n", __func__, rc);
		return false;
	}
	pdata[0] = params[0].u.value.a & 0xff;
	pdata[1] = params[1].u.value.a & 0xff;
	return true;
}

bool fgCaHDMILoadHDCPKey(void)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return false;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	arg.func = HDMI_TA_LOAD_HDCP_KEY;

	/* cmd id */
	memset(params, 0, sizeof(params));
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = 0;
	params[0].u.value.b = 0;

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc) {
		TX_DEF_LOG("[CA] HDMI_TA_LOAD_HDCP_KEY err:%X\n", rc);
		return false;
	}
	return true;
}


bool fgCaHDMILoadROM(void)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return false;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	arg.func = HDMI_TA_LOAD_ROM;

	/* cmd id */
	memset(params, 0, sizeof(params));
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = 0;
	params[0].u.value.b = 0;

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc) {
		TX_DEF_LOG("[CA] HDMI_TA_LOAD_HDCP_KEY err:%X\n", rc);
		return false;
	}
	return true;

}

bool fgCaHDMITestHDCPVersion(void)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return false;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	arg.func = HDMI_TA_TEST_HDCP_VERSION;

	/* cmd id */
	memset(params, 0, sizeof(params));
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = 0;
	params[0].u.value.b = 0;

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc) {
		TX_DEF_LOG("[CA] HDMI_TA_LOAD_HDCP_KEY err:%X\n", rc);
		return false;
	}
	return true;
}

void fgCaHDMISetTzLogLevel(unsigned int loglevel)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	arg.func = HDMI_TA_SET_LOG_LEVEL;

	/* cmd id */
	memset(params, 0, sizeof(params));
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = loglevel;
	params[0].u.value.b = 0;

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc)
		TX_DEF_LOG("[CA] HDMI_TA_LOAD_HDCP_KEY err:%X\n", rc);
}

void fgCaHDMISetSecureRegEntry(unsigned int Tx_entry,
	unsigned int Rx_entry)
{
	int rc = 0;
	struct tee_ioctl_invoke_arg arg;
	struct tee_param params[TEEC_PAYLOAD_REF_COUNT];

	if (hdmitx_session_arg.session == 0) {
		TX_DEF_LOG("[CA]TEE hdmitx_session_handle=0\n");
		return;
	}

	/* invoke cmd */
	memset(&arg, 0, sizeof(arg));
	arg.num_params = TEEC_PAYLOAD_REF_COUNT;
	arg.session = hdmitx_session_arg.session;
	arg.func = HDMI_TA_SECURE_REG_ENTRY;

	/* cmd id */
	memset(params, 0, sizeof(params));
	params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = Tx_entry;
	params[0].u.value.b = 0;
	params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[1].u.value.a = Rx_entry;
	params[1].u.value.b = 0;

	rc = tee_client_invoke_func(hdmitx_tee_ctx, &arg, params);
	if (rc)
		TX_DEF_LOG("[CA] %s(): rc = %d\n", __func__, rc);
}

#endif



#endif
