/*
 * Copyright 2024 Sony Corporation
 */

#include <command.h>
#include <common.h>
#include <utility.h>
#include <iniparser.h>
#include <iniutility.h>
#include <debug_impl.h>
#include <fs.h>
#include <dm/device.h>
#include <dm/uclass.h>
#include <serial.h>
#include "ldbe_boot.h"

/*
 * ------- normal sequence test ----------
 */
static int boot_seq_mode0_cb(u_char *outp, int *outp_len, int retry_flag, int even_odd_flag, void *param)
{
	int len, i;
	u_char *inp;
	char buf[3] = {0};

	inp = (u_char *)param;
	len = strlen((const char *)inp);
	if (len == 0 || (len % 2) != 0)
		return -1;

	len /= 2;
	for (i = 0; i < len; i++) {
		snprintf(buf, sizeof(buf), "%c%c", inp[0], inp[1]);
		outp[i + _PROXYLAYER_OFFSET_] = (u_char)strtoul(buf, NULL, 16);
		inp += 2;
	}

	return ldbe_boot_convert_to_ldbe_protocol(outp, outp_len, len, retry_flag, even_odd_flag);
}

static int boot_seq_mode1_cb(u_char *outp, int *outp_len, int retry_flag, int even_odd_flag, void *param)
{
	int len, i;
	u_char *inp;
	char buf[3] = {0};

	inp = (u_char *)param;
	len = strlen((const char *)inp);
	if (len == 0 || (len % 2) != 0)
		return -1;

	len /= 2;
	for (i = 0; i < len; i++) {
		snprintf(buf, sizeof(buf), "%c%c", inp[0], inp[1]);
		outp[i] = (u_char)strtoul(buf, NULL, 16);
		inp += 2;
	}

	*outp_len = len;

	return 0;
}

// arg1: mode, 0 is input-proxy, 1 is input-linklayer
// arg2: linklayer or proxylayer data hex string
//       2 hex digits (without 0x)
//      ex) 000a0A11
// arg3: baudrate(optional, default 921600bps)
static int do_ldbe_boot_seq(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	struct udevice *udev;
	int ret = 0;
	int baudrate = 921600;
	int mode;

	// argc = 2 is mode argv[1]
	// argc = 3 is data argv[2]
	// argc = 4 is bps  argv[3]
	UBOOT_TRACE("IN\n");
	if (argc < 3)
		return -1;

	// optional: set baudrate value
	if (argc > 3 && argv[3] != NULL)
		baudrate = strtoul(argv[3], NULL, 10);
	UBOOT_INFO("baudrate = %d bps\n", baudrate);

	ret = uclass_get_device_by_name(UCLASS_SERIAL, LDBE_UART_NAME, &udev);
	if (ret) {
		UBOOT_ERROR("serial device not found by name %s\n", LDBE_UART_NAME);
		return ret;
	}

	//default baudrate is 921600bps
	ret = ldbe_boot_setbrg(udev, baudrate);
	if (ret)
		return ret;

	mode = strtoul(argv[1], NULL, 10);
	UBOOT_INFO("input mode = %s\n", (mode == 0) ? "proxylayer" : "linklayer");

	if (mode == 0)
		ret = ldbe_boot_send_cmd_no_reply(udev, boot_seq_mode0_cb, (void *)argv[2]);
	else
		ret = ldbe_boot_send_cmd_no_reply(udev, boot_seq_mode1_cb, (void *)argv[2]);

	if (ret) {
		UBOOT_ERROR("seq test: Command transmission has failed, so the command will be aborted.\n");
		return 0;
	}

	UBOOT_TRACE("OUT\n");

	return 0;
}

U_BOOT_CMD(
		ldbe_boot_seq, CONFIG_SYS_MAXARGS, 0, do_ldbe_boot_seq,
		"DEBUG LDBE boot cmd(sequence test)",
		NULL
		);

/*
 * ------- abnormal sequence test ----------
 */

// All transmissions, including retransmissions
// mode: wrong CRC
// expected behavior: all NACK(CRC)
static int boot_seq2_mode0_cb(u_char *outp, int *outp_len, int retry_flag, int even_odd_flag, void *param)
{
	int len, i;
	int ret;
	u_char *inp;
	char buf[3] = {0};

	inp = (u_char *)param;
	len = strlen((const char *)inp);
	if (len == 0 || (len % 2) != 0)
		return -1;

	len /= 2;
	for (i = 0; i < len; i++) {
		snprintf(buf, sizeof(buf), "%c%c", inp[0], inp[1]);
		outp[i + _PROXYLAYER_OFFSET_] = (u_char)strtoul(buf, NULL, 16);
		inp += 2;
	}

	ret = ldbe_boot_convert_to_ldbe_protocol(outp, outp_len, len, retry_flag, even_odd_flag);

	// Rewrite to the wrong CRC
	outp[*outp_len - 1] ^= 0xff;

	return ret;
}

// All transmissions, including retransmissions
// mode: wrong ISOF
// expected behavior: all TX timeout
static int boot_seq2_mode1_cb(u_char *outp, int *outp_len, int retry_flag, int even_odd_flag, void *param)
{
	int len, i;
	int ret;
	u_char *inp;
	char buf[3] = {0};

	inp = (u_char *)param;
	len = strlen((const char *)inp);
	if (len == 0 || (len % 2) != 0)
		return -1;

	len /= 2;
	for (i = 0; i < len; i++) {
		snprintf(buf, sizeof(buf), "%c%c", inp[0], inp[1]);
		outp[i + _PROXYLAYER_OFFSET_] = (u_char)strtoul(buf, NULL, 16);
		inp += 2;
	}

	ret = ldbe_boot_convert_to_ldbe_protocol(outp, outp_len, len, retry_flag, even_odd_flag);

	// Rewrite to the wrong ISOF
	outp[1] = outp[1] ^ 0xff;

	return ret;
}

// All transmissions, including retransmissions
// mode: wrong SIZE(larger size)
// expected behavior: all NACK(timeout)
static int boot_seq2_mode2_cb(u_char *outp, int *outp_len, int retry_flag, int even_odd_flag, void *param)
{
	int len, i;
	int ret;
	u_char *inp;
	char buf[3] = {0};
	u_short size;

	inp = (u_char *)param;
	len = strlen((const char *)inp);
	if (len == 0 || (len % 2) != 0)
		return -1;

	len /= 2;
	for (i = 0; i < len; i++) {
		snprintf(buf, sizeof(buf), "%c%c", inp[0], inp[1]);
		outp[i + _PROXYLAYER_OFFSET_] = (u_char)strtoul(buf, NULL, 16);
		inp += 2;
	}

	ret = ldbe_boot_convert_to_ldbe_protocol(outp, outp_len, len, retry_flag, even_odd_flag);

	// Rewrite to the wrong SIZE
	size = be16_to_cpu(*(u_short *)(outp + 2));
	size += 1;
	*(u_short *)(outp + 2) = cpu_to_be16(size); // size

	return ret;
}

// mode: 1st tx: wrong CRC, 2nd tx: correct packet
// expected behavior: 1st tx is NACK(CRC), 2nd tx is ACK
static int boot_seq2_mode3_cb(u_char *outp, int *outp_len, int retry_flag, int even_odd_flag, void *param)
{
	int len, i;
	int ret;
	u_char *inp;
	char buf[3] = {0};

	inp = (u_char *)param;
	len = strlen((const char *)inp);
	if (len == 0 || (len % 2) != 0)
		return -1;

	len /= 2;
	for (i = 0; i < len; i++) {
		snprintf(buf, sizeof(buf), "%c%c", inp[0], inp[1]);
		outp[i + _PROXYLAYER_OFFSET_] = (u_char)strtoul(buf, NULL, 16);
		inp += 2;
	}

	ret = ldbe_boot_convert_to_ldbe_protocol(outp, outp_len, len, retry_flag, even_odd_flag);

	// Only the first send will send to the wrong CRC
	if (retry_flag == 0)
		outp[*outp_len - 1] ^= 0xff; // Rewrite to the wrong CRC

	return ret;
}

// mode: 1st tx: wrong ISOF, 2nd tx: correct packet
// expected behavior: 1st tx is TX timeout, 2nd tx is ACK
static int boot_seq2_mode4_cb(u_char *outp, int *outp_len, int retry_flag, int even_odd_flag, void *param)
{
	int len, i;
	int ret;
	u_char *inp;
	char buf[3] = {0};

	inp = (u_char *)param;
	len = strlen((const char *)inp);
	if (len == 0 || (len % 2) != 0)
		return -1;

	len /= 2;
	for (i = 0; i < len; i++) {
		snprintf(buf, sizeof(buf), "%c%c", inp[0], inp[1]);
		outp[i + _PROXYLAYER_OFFSET_] = (u_char)strtoul(buf, NULL, 16);
		inp += 2;
	}

	ret = ldbe_boot_convert_to_ldbe_protocol(outp, outp_len, len, retry_flag, even_odd_flag);

	// Only the first send will send to the wrong ISOF
	if (retry_flag == 0)
		outp[1] = outp[1] ^ 0xff;// Rewrite to the wrong ISOF

	return ret;
}

// mode: 1st tx: wrong SIZE(larger size), 2nd tx: correct packet
// expected behavior: 1st tx is NACK(timeout), 2nd tx is ACK
static int boot_seq2_mode5_cb(u_char *outp, int *outp_len, int retry_flag, int even_odd_flag, void *param)
{
	int len, i;
	int ret;
	u_char *inp;
	char buf[3] = {0};
	//u_short size;

	inp = (u_char *)param;
	len = strlen((const char *)inp);
	if (len == 0 || (len % 2) != 0)
		return -1;

	len /= 2;
	for (i = 0; i < len; i++) {
		snprintf(buf, sizeof(buf), "%c%c", inp[0], inp[1]);
		outp[i + _PROXYLAYER_OFFSET_] = (u_char)strtoul(buf, NULL, 16);
		inp += 2;
	}

	ret = ldbe_boot_convert_to_ldbe_protocol(outp, outp_len, len, retry_flag, even_odd_flag);

	//size = be16_to_cpu(*(u_short *)(outp + 2));

	// Only the first send will send less than SIZE
	if (retry_flag == 0)
		*outp_len = 4;

	return ret;
}

// Abnormal data transmission test
// arg1: mode, 0 is wrong CRC, 1 is wrong ISOF, 2 is wrong SIZE
// arg2: proxylayer data hex string
//       2 hex digits (without 0x)
//      ex) 000a0A11
// arg3: baudrate(optional, default 921600bps)
static int do_ldbe_boot_seq2(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	struct udevice *udev;
	int ret = 0;
	int baudrate = 921600;
	int mode;

	// argc = 2 is mode argv[1]
	// argc = 3 is data argv[2]
	// argc = 4 is bps  argv[3]
	UBOOT_TRACE("IN\n");
	if (argc < 3)
		return -1;

	// optional: set baudrate value
	if (argc > 3 && argv[3] != NULL)
		baudrate = strtoul(argv[3], NULL, 10);
	UBOOT_INFO("baudrate = %d bps\n", baudrate);

	ret = uclass_get_device_by_name(UCLASS_SERIAL, LDBE_UART_NAME, &udev);
	if (ret) {
		UBOOT_ERROR("serial device not found by name %s\n", LDBE_UART_NAME);
		return ret;
	}

	//default baudrate is 921600bps
	ret = ldbe_boot_setbrg(udev, baudrate);
	if (ret)
		return ret;

	mode = strtoul(argv[1], NULL, 10);
	if (mode == 0) {
		UBOOT_INFO("mode: wrong CRC\n");
		ret = ldbe_boot_send_cmd_no_reply(udev, boot_seq2_mode0_cb, (void *)argv[2]);
	} else if (mode == 1) {
		UBOOT_INFO("mode: wrong ISOF\n");
		ret = ldbe_boot_send_cmd_no_reply(udev, boot_seq2_mode1_cb, (void *)argv[2]);
	} else if (mode == 2) {
		UBOOT_INFO("mode: wrong SIZE(larger size)\n");
		ret = ldbe_boot_send_cmd_no_reply(udev, boot_seq2_mode2_cb, (void *)argv[2]);
	} else if (mode == 3) {
		UBOOT_INFO("mode: 1st tx: wrong CRC, 2nd tx: correct packet\n");
		ret = ldbe_boot_send_cmd_no_reply(udev, boot_seq2_mode3_cb, (void *)argv[2]);
	} else if (mode == 4) {
		UBOOT_INFO("mode: 1st tx: wrong ISOF, 2nd tx: correct packet\n");
		ret = ldbe_boot_send_cmd_no_reply(udev, boot_seq2_mode4_cb, (void *)argv[2]);
	} else if (mode == 5) {
		UBOOT_INFO("mode: 1st tx: wrong SIZE(larger size), 2nd tx: correct packet\n");
		ret = ldbe_boot_send_cmd_no_reply(udev, boot_seq2_mode5_cb, (void *)argv[2]);
	} else {
		UBOOT_INFO("Unsupported mode number: %d\n", mode);
	}

	if (ret) {
		UBOOT_ERROR("seq test: Command transmission has failed, so the command will be aborted.\n");
		return 0;
	}

	UBOOT_TRACE("OUT\n");

	return 0;
}

U_BOOT_CMD(
		ldbe_boot_seq2, CONFIG_SYS_MAXARGS, 0, do_ldbe_boot_seq2,
		"DEBUG LDBE boot cmd(abnormal sequence test)",
		NULL
		);

/*
 * ------- fuart test ----------
 */

// TX only test
// arg1: Send data (ASCII code string)
// arg2: baudrate(optional, default 921600bps)
static int do_ldbe_boot_tx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	struct udevice *udev;
	int ret = 0;
	int baudrate = 921600;
	u_long t0;
	u_char *inp;

	UBOOT_TRACE("IN\n");
	//UBOOT_INFO("ulong = %lu, uint = %lu, ulongint = %lu\n", sizeof(unsigned long), sizeof(unsigned int), sizeof(unsigned long int));

	if (argc < 2)
		return -1;

	// optional: set baudrate value
	if (argc > 2 && argv[2] != NULL)
		baudrate = strtoul(argv[2], NULL, 10);
	UBOOT_INFO("baudrate = %d bps\n", baudrate);

	ret = uclass_get_device_by_name(UCLASS_SERIAL, LDBE_UART_NAME, &udev);
	if (ret) {
		UBOOT_ERROR("serial device not found by name %s\n", LDBE_UART_NAME);
		return ret;
	}

	//default baudrate is 921600bps
	ret = ldbe_boot_setbrg(udev, baudrate);
	if (ret)
		return ret;

	inp = (u_char *)argv[1];
	t0 = timer_get_boot_us();
	ldbe_boot_uart_transfer(udev, LDBE_UART_WRITE, t0, (3000 * 1000), inp, strlen(argv[1]));

	UBOOT_TRACE("OUT\n");

	return 0;
}

U_BOOT_CMD(
		ldbe_boot_tx, CONFIG_SYS_MAXARGS, 0, do_ldbe_boot_tx,
		"DEBUG LDBE boot cmd(TX only test, ASCII code string)",
		NULL
		);

// TX only test2
// arg1: Send data (2 hex digits (without 0x))
//       ex) 000a0A11
// arg2: baudrate(optional, default 921600bps)
static int do_ldbe_boot_tx2(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	struct udevice *udev;
	u_char *txdata, *inp;
	int len, i, ret = 0;
	int baudrate = 921600;
	u_long t0;
	char buf[3] = {0};

	UBOOT_TRACE("IN\n");
	if (argc < 2)
		return -1;

	// optional: set baudrate value
	if (argc > 2 && argv[2] != NULL)
		baudrate = strtoul(argv[2], NULL, 10);
	UBOOT_INFO("baudrate = %d bps\n", baudrate);

	len = strlen(argv[1]);
	if (len == 0 || (len % 2) != 0)
		return -1;

	inp = (u_char *)argv[1];

	len /= 2;
	txdata = malloc(len);
	if (txdata == NULL)
		return -1;

	memset(txdata, 0, len);

	for (i = 0; i < len; i++) {
		snprintf(buf, sizeof(buf), "%c%c", inp[0], inp[1]);
		txdata[i] = (u_char)strtoul(buf, NULL, 16);
		inp += 2;
	}

	UBOOT_INFO("input senddata: ");
	for (i = 0; i < len; i++)
		UBOOT_INFO("0x%02x, ", txdata[i]);
	UBOOT_INFO("\n");

	ret = uclass_get_device_by_name(UCLASS_SERIAL, LDBE_UART_NAME, &udev);
	if (ret) {
		UBOOT_ERROR("serial device not found by name %s\n", LDBE_UART_NAME);
		free(txdata);
		return ret;
	}

	//default baudrate is 921600bps
	ret = ldbe_boot_setbrg(udev, baudrate);
	if (ret) {
		free(txdata);
		return ret;
	}


	t0 = timer_get_boot_us();
	ldbe_boot_uart_transfer(udev, LDBE_UART_WRITE, t0, (3000 * 1000), txdata, len);
	free(txdata);

	UBOOT_TRACE("OUT\n");

	return 0;
}

U_BOOT_CMD(
		ldbe_boot_tx2, CONFIG_SYS_MAXARGS, 0, do_ldbe_boot_tx2,
		"DEBUG LDBE boot cmd(TX only test2, 2 hex digits (without 0x))",
		NULL
		);

// RX only test
// arg1: rx data size(optional, default 4 bytes)
// arg2: rx timeout(optional, units:ms, default 3000ms)
// arg3: baudrate(optional, default 921600bps)
static int do_ldbe_boot_rx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	struct udevice *udev;
	u_char *rxdata;
	int len, i, to, ret = 0;
	int baudrate;
	u_long stm;

	UBOOT_TRACE("IN\n");

	len = 4;
	to = 3000;
	baudrate = 921600;

	// optional: set recive length
	if (argc > 1 && argv[1] != NULL)
		len = strtoul(argv[1], NULL, 10);

	// optional: set timeout value
	if (argc > 2 && argv[2] != NULL)
		to = strtoul(argv[2], NULL, 10);

	// optional: set baudrate value
	if (argc > 3 && argv[3] != NULL)
		baudrate = strtoul(argv[3], NULL, 10);
	UBOOT_INFO("rx size = %d, timeout = %d, baudrate = %d bps\n", len, to, baudrate);

	ret = uclass_get_device_by_name(UCLASS_SERIAL, LDBE_UART_NAME, &udev);
	if (ret) {
		UBOOT_ERROR("serial device not found by name %s\n", LDBE_UART_NAME);
		return ret;
	}

	//default baudrate is 921600bps
	ret = ldbe_boot_setbrg(udev, baudrate);
	if (ret)
		return ret;

	rxdata = malloc(len);
	if (rxdata == NULL)
		return -1;

	memset(rxdata, 0, len);

	stm = timer_get_boot_us();
	ret = ldbe_boot_uart_transfer(udev, LDBE_UART_READ, stm, (to * 1000), rxdata, len);

	if (ret) {
		UBOOT_INFO("RX: ");
		for (i = 0; i < len; i++)
			UBOOT_INFO("0x%02x, ", rxdata[i]);
		UBOOT_INFO("\n");
	}

	free(rxdata);

	UBOOT_TRACE("OUT\n");

	return 0;
}

U_BOOT_CMD(
		ldbe_boot_rx, CONFIG_SYS_MAXARGS, 0, do_ldbe_boot_rx,
		"DEBUG LDBE boot cmd(RX only test)",
		NULL
		);

// uart port dump
int do_ldbe_boot_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	UBOOT_INFO("IN\n");
	ldbe_boot_dump_uclass_serial();
	UBOOT_INFO("OUT\n");

	return 0;
}

U_BOOT_CMD(
		ldbe_boot_dump, CONFIG_SYS_MAXARGS, 0, do_ldbe_boot_dump,
		"DEBUG LDBE boot(uart port dump)",
		NULL
		);

/*
 * ------- boot command test ----------
 */
// A sequence of one selected command
// arg1 : command id
// arg2~argN : command parameter
static int do_ldbe_boot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	struct udevice *udev;
	int ret, commandid;
	u_char is_force_retrain;
	u_char scan_mode;
	u_char swing_level;
	u_char pre_de_emphasis;
	u_char output_signal;
	u_char dlg_mode;
	u_char mute_control;
	struct ldbe_boot_param_SetTvVby1SSCControl param1 = {0};
	struct ldbe_boot_param_SetPixelMute param2 = {0};

	UBOOT_TRACE("IN\n");
	if (argc < 2)
		return -1;

	ret = ldbe_boot_fuart_init(&udev);
	if (ret)
		return 0;

	commandid = (int)strtoul(argv[1], NULL, 0);

	switch (commandid) {
	case LDBE_CMDID_DISP_SET_PIXELMUTE:
		// DISP_SetPixelMute
		UBOOT_INFO("DISP_SetPixelMute\n");
		if (argc < 4) {
			UBOOT_ERROR("Not enough arguments\n");
			return 0;
		}

		// argc = 2 is command id, argv[1]
		// argc = 3 is mute_color, argv[2]
		// argc = 4 is pixel_mute, argv[3]
		// argc = 5 is rgb_r, argv[4]
		// argc = 6 is rgb_g, argv[5]
		// argc = 7 is rgb_b, argv[6]
		param2.mute_color = (u_char)strtoul(argv[2], NULL, 0);
		param2.pixel_mute = (u_char)strtoul(argv[3], NULL, 0);
		if (argc > 4 && argv[4] != NULL)
			param2.rgb_r = (u_short)strtoul(argv[4], NULL, 0);
		if (argc > 5 && argv[5] != NULL)
			param2.rgb_g = (u_short)strtoul(argv[5], NULL, 0);
		if (argc > 6 && argv[6] != NULL)
			param2.rgb_b = (u_short)strtoul(argv[6], NULL, 0);

		ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetPixelMute_cb, (void *)&param2);
		if (ret)
			UBOOT_ERROR("DISP_SetPixelMute: Command transmission has failed, so the command will be aborted.\n");
		break;

	case LDBE_CMDID_DISP_SET_RX_VBY1_CONTROL:
		// DISP_SetRxVby1ControlRetrain
		UBOOT_INFO("DISP_SetRxVby1ControlRetrain\n");
		if (argc < 3) {
			UBOOT_ERROR("Not enough arguments\n");
			return 0;
		}

		// argc = 2 is command id, argv[1]
		// argc = 3 is is_force_retrain, argv[2]
		is_force_retrain = (u_char)strtoul(argv[2], NULL, 0);
		ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetRxVby1ControlRetrain_cb, (void *)&is_force_retrain);
		if (ret)
			UBOOT_ERROR("DISP_SetRxVby1ControlRetrain: Command transmission has failed, so the command will be aborted.\n");
		break;

	case LDBE_CMDID_DISP_SET_TX_VBY1_CONTROL_RETRAIN:
		UBOOT_INFO("DISP_SetTxVby1ControlRetrain\n");
		if (argc < 3) {
			UBOOT_ERROR("Not enough arguments\n");
			return 0;
		}

		// argc = 2 is command id, argv[1]
		// argc = 3 is is_force_retrain, argv[2]
		is_force_retrain = (u_char)strtoul(argv[2], NULL, 0);
		ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetTxVby1ControlRetrain_cb, (void *)&is_force_retrain);
		if (ret)
			UBOOT_ERROR("DISP_SetTxVby1ControlRetrain: Command transmission has failed, so the command will be aborted.\n");
		break;

	case LDBE_CMDID_DISP_SET_TX_VBY1_SCAN_MODE:
		// DISP_SetTxVby1ScanMode
		UBOOT_INFO("DISP_SetTxVby1ScanMode\n");
		if (argc < 3) {
			UBOOT_ERROR("Not enough arguments\n");
			return 0;
		}

		// argc = 2 is command id, argv[1]
		// argc = 3 is scan_mode, argv[2]
		scan_mode = (u_char)strtoul(argv[2], NULL, 0);
		ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetTxVby1ScanMode_cb, (void *)&scan_mode);
		if (ret)
			UBOOT_ERROR("DISP_SetTxVby1ScanMode: Command transmission has failed, so the command will be aborted.\n");
		break;

	case LDBE_CMDID_DISP_SET_TX_VBY1_SWING_LEVEL:
		// DISP_SetTxVby1SwingLevel
		UBOOT_INFO("DISP_SetTxVby1SwingLevel\n");
		if (argc < 3) {
			UBOOT_ERROR("Not enough arguments\n");
			return 0;
		}

		// argc = 2 is command id, argv[1]
		// argc = 3 is swing_level, argv[2]
		swing_level = (u_char)strtoul(argv[2], NULL, 0);
		ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetTxVby1SwingLevel_cb, (void *)&swing_level);
		if (ret)
			UBOOT_ERROR("DISP_SetTxVby1SwingLevel: Command transmission has failed, so the command will be aborted.\n");
		break;

	case LDBE_CMDID_DISP_SET_TX_VBY1_PRE_DE_EMPHASIS:
		// DISP_SetTxVby1PreDEEmphasis
		UBOOT_INFO("DISP_SetTxVby1PreDEEmphasis\n");
		if (argc < 3) {
			UBOOT_ERROR("Not enough arguments\n");
			return 0;
		}

		// argc = 2 is command id, argv[1]
		// argc = 3 is pre_de_emphasis, argv[2]
		pre_de_emphasis = (u_char)strtoul(argv[2], NULL, 0);
		ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetTxVby1PreDEEmphasis_cb, (void *)&pre_de_emphasis);
		if (ret)
			UBOOT_ERROR("DISP_SetTxVby1PreDEEmphasis: Command transmission has failed, so the command will be aborted.\n");
		break;

	case LDBE_CMDID_DISP_SET_TX_VBY1_OUTPUT_ENABLE:
		// DISP_SetTxVby1OutputEnable
		UBOOT_INFO("DISP_SetTxVby1OutputEnable\n");
		if (argc < 3) {
			UBOOT_ERROR("Not enough arguments\n");
			return 0;
		}

		// argc = 2 is command id, argv[1]
		// argc = 3 is output_signal, argv[2]
		output_signal = (u_char)strtoul(argv[2], NULL, 0);
		ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetTxVby1OutputEnable_cb, (void *)&output_signal);
		if (ret)
			UBOOT_ERROR("DISP_SetTxVby1OutputEnable: Command transmission has failed, so the command will be aborted.\n");
		break;

	case LDBE_CMDID_DISP_SET_TX_VBY1_SSC_CONTROL:
		// DISP_SetTxVby1SSCControl
		UBOOT_INFO("DISP_SetTxVby1SSCControl\n");
		if (argc < 5) {
			UBOOT_ERROR("Not enough arguments\n");
			return 0;
		}

		// argc = 2 is command id, argv[1]
		// argc = 3 is control_enable, argv[2]
		// argc = 4 is modulation, argv[3]
		// argc = 5 is deviation, argv[4]
		param1.control_enable = (u_char)strtoul(argv[2], NULL, 0);
		param1.modulation = (u_char)strtoul(argv[3], NULL, 0);
		param1.deviation = (u_char)strtoul(argv[4], NULL, 0);
		ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetTxVby1SSCControl_cb, (void *)&param1);
		if (ret)
			UBOOT_ERROR("DISP_SetTxVby1SSCControl: Command transmission has failed, so the command will be aborted.\n");
		break;

	case LDBE_CMDID_DISP_SET_TX_VBY1_DLG_CONTROL:
		// DISP_SetTxVby1DLGControl
		UBOOT_INFO("DISP_SetTxVby1DLGControl\n");
		if (argc < 3) {
			UBOOT_ERROR("Not enough arguments\n");
			return 0;
		}

		// argc = 2 is command id, argv[1]
		// argc = 3 is dlg_mode, argv[2]
		dlg_mode = (u_char)strtoul(argv[2], NULL, 0);
		ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetTxVby1DLGControl_cb, (void *)&dlg_mode);
		if (ret)
			UBOOT_ERROR("DISP_SetTxVby1DLGControl: Command transmission has failed, so the command will be aborted.\n");
		break;

	case LDBE_CMDID_DISP_SET_MUTE_CONTROL:
		// DISP_SetMuteControl
		UBOOT_INFO("DISP_SetMuteControl\n");
		if (argc < 3) {
			UBOOT_ERROR("Not enough arguments\n");
			return 0;
		}

		// argc = 2 is command id, argv[1]
		// argc = 3 is mute_control, argv[2]
		mute_control = (u_char)strtoul(argv[2], NULL, 0);
		ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetMuteControl_cb, (void *)&mute_control);
		if (ret)
			UBOOT_ERROR("DISP_SetMuteControl: Command transmission has failed, so the command will be aborted.\n");
		break;

	default:
		UBOOT_ERROR("Invalid command ID\n");
		return 0;
	}

	UBOOT_TRACE("OUT\n");

	return 0;
}

U_BOOT_CMD(
		ldbe_boot_cmd, CONFIG_SYS_MAXARGS, 0, do_ldbe_boot_cmd,
		"LDBE boot cmd(A sequence of one selected command)",
		NULL
		);

// LDBE_DISP_SetTxVby1SSCControl Cmd Test
// arg1 : control_enable
// arg2 : modulation
// arg3 : deviation
static int do_ldbe_boot_SSCControl(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	struct udevice *udev;
	int ret;
	u_char control_enable = 0;
	u_char modulation = 0;
	u_char deviation = 0;
	struct ldbe_boot_param_SetTvVby1SSCControl param;

	UBOOT_TRACE("IN\n");
	ret = ldbe_boot_fuart_init(&udev);
	if (ret)
		return 0;

	if (argc > 1 && argv[1] != NULL)
		control_enable = strtoul(argv[1], NULL, 10);

	if (argc > 2 && argv[2] != NULL)
		modulation = strtoul(argv[2], NULL, 10);

	if (argc > 3 && argv[3] != NULL)
		deviation = strtoul(argv[2], NULL, 10);


	// DISP_SetTxVby1SSCControl
	UBOOT_INFO("DISP_SetTxVby1SSCControl\n");
	param.control_enable = control_enable;
	param.modulation = modulation;
	param.deviation = deviation;
	ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetTxVby1SSCControl_cb, (void *)&param);
	if (ret) {
		UBOOT_ERROR("DISP_SetTxVby1SSCControl: Command transmission has failed, so the command will be aborted.\n");
		return 0;
	}

	UBOOT_TRACE("OUT\n");

	return 0;
}

U_BOOT_CMD(
		ldbe_boot_sscc, CONFIG_SYS_MAXARGS, 0, do_ldbe_boot_SSCControl,
		"DEBUG LDBE boot cmd(LDBE_DISP_SetTxVby1SSCControl)",
		NULL
		);

// LDBE_DISP_SetPixelMute Cmd Test
// arg1 : mute_color
// arg2 : pixel_mute
// arg3 : rgb red   (0x for hex)
// arg4 : rgb green (0x for hex)
// arg5 : rgb blue  (0x for hex)
static int do_ldbe_boot_SetPixelMute(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	struct udevice *udev;
	int ret;
	u_char mute_color = 0;
	u_char pixel_mute = 0;
	u_short rgb_r = 0;
	u_short rgb_g = 0;
	u_short rgb_b = 0;
	struct ldbe_boot_param_SetPixelMute param;

	UBOOT_TRACE("IN\n");
	ret = ldbe_boot_fuart_init(&udev);
	if (ret)
		return 0;

	if (argc > 1 && argv[1] != NULL)
		mute_color = strtoul(argv[1], NULL, 10);

	if (argc > 2 && argv[2] != NULL)
		pixel_mute = strtoul(argv[2], NULL, 10);

	if (argc > 3 && argv[3] != NULL)
		rgb_r = strtoul(argv[3], NULL, 0);

	if (argc > 4 && argv[4] != NULL)
		rgb_g = strtoul(argv[4], NULL, 0);

	if (argc > 5 && argv[5] != NULL)
		rgb_b = strtoul(argv[5], NULL, 0);

	// DISP_SetPixelMute
	UBOOT_INFO("DISP_SetPixelMute\n");
	param.mute_color = mute_color;
	param.pixel_mute = pixel_mute;
	param.rgb_r = rgb_r;
	param.rgb_g = rgb_g;
	param.rgb_b = rgb_b;
	ret = ldbe_boot_send_cmd_no_reply(udev, LDBE_DISP_SetPixelMute_cb, (void *)&param);
	if (ret) {
		UBOOT_ERROR("DISP_SetPixelMute: Command transmission has failed, so the command will be aborted.\n");
		return 0;
	}

	UBOOT_TRACE("OUT\n");

	return 0;
}

U_BOOT_CMD(
		ldbe_boot_pixelmute, CONFIG_SYS_MAXARGS, 0, do_ldbe_boot_SetPixelMute,
		"DEBUG LDBE boot cmd(LDBE_DISP_SetPixelMute)",
		NULL
		);
