/*
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <i2c.h>
#include <zephyr.h>
#include <ztest.h>

/*
 * For ADV7513 Programming details, please
 * refer to the following link.
 * https://ez.analog.com/docs/DOC-1986
 */

#define ADV7513_HDMI_I2C_SLAVE_ADDR	0x39

#define ADV7513_CHIP_REVISION_REG	0x0
#define CHIP_REVISION_VAL		0x13

#define ADV7513_MAIN_POWER_REG		0x41
#define POWER_ON_VAL			0x10

#define ADV7513_HPD_CTRL_REG		0xD6
#define HPD_CTRL_VAL			0xC0

#define ADV7513_WRITE_TEST_REG		0x2
#define WRITE_TEST_VAL			0x66

static int powerup_adv7513(struct device *i2c_dev)
{
	u8_t data;

	TC_PRINT("Powering up ADV7513\n");
	/* write to HPD control registers */
	if (i2c_reg_write_byte(i2c_dev, ADV7513_HDMI_I2C_SLAVE_ADDR,
				ADV7513_HPD_CTRL_REG, HPD_CTRL_VAL)) {
		TC_PRINT("i2c write fail\n");
		return TC_FAIL;
	}
	if (i2c_reg_read_byte(i2c_dev, ADV7513_HDMI_I2C_SLAVE_ADDR,
				0xD6, &data)) {
		TC_PRINT("failed to read HPD control\n");
		return TC_FAIL;
	}
	TC_PRINT("HPD control 0x%x\n", data);

	/* write to power control registers */
	if (i2c_reg_write_byte(i2c_dev, ADV7513_HDMI_I2C_SLAVE_ADDR,
				ADV7513_MAIN_POWER_REG, POWER_ON_VAL)) {
		TC_PRINT("i2c write fail\n");
		return TC_FAIL;
	}

	if (i2c_reg_read_byte(i2c_dev, ADV7513_HDMI_I2C_SLAVE_ADDR,
				0x41, &data)) {
		TC_PRINT("failed to read Power state\n");
		return TC_FAIL;
	}
	TC_PRINT("Power state 0x%x\n", data);

	return TC_PASS;
}

static int test_i2c_adv7513(void)
{
	struct device *i2c_dev = device_get_binding(CONFIG_I2C_0_NAME);
	u32_t i2c_cfg = I2C_SPEED_SET(I2C_SPEED_STANDARD) | I2C_MODE_MASTER;
	u8_t data;

	if (!i2c_dev) {
		TC_PRINT("cannot get i2c device\n");
		return TC_FAIL;
	}

	/* Test i2c_configure() */
	if (i2c_configure(i2c_dev, i2c_cfg)) {
		TC_PRINT("i2c config failed\n");
		return TC_FAIL;
	}

	/* Power up ADV7513 */
	zassert_true(powerup_adv7513(i2c_dev) == TC_PASS,
					"ADV7513 power up failed");

	TC_PRINT("*** Running i2c read/write tests ***\n");
	/* Test i2c byte read */
	data = 0x0;
	if (i2c_reg_read_byte(i2c_dev, ADV7513_HDMI_I2C_SLAVE_ADDR,
				ADV7513_CHIP_REVISION_REG, &data)) {
		TC_PRINT("failed to read chip revision\n");
		return TC_FAIL;
	}
	if (data != CHIP_REVISION_VAL) {
		TC_PRINT("chip revision does not match 0x%x\n", data);
		return TC_FAIL;
	}
	TC_PRINT("i2c read test passed\n");


	/* Test i2c byte write */
	data = WRITE_TEST_VAL;
	if (i2c_reg_write_byte(i2c_dev, ADV7513_HDMI_I2C_SLAVE_ADDR,
				ADV7513_WRITE_TEST_REG, data)) {
		TC_PRINT("i2c write fail\n");
		return TC_FAIL;
	}
	data = 0x0;
	if (i2c_reg_read_byte(i2c_dev, ADV7513_HDMI_I2C_SLAVE_ADDR,
				ADV7513_WRITE_TEST_REG, &data)) {
		TC_PRINT("i2c read fail\n");
		return TC_FAIL;
	}
	if (data != WRITE_TEST_VAL) {
		TC_PRINT("i2c write test failed 0x%x\n", data);
		return TC_FAIL;
	}
	TC_PRINT("i2c write & verify test passed\n");

	return TC_PASS;
}

void test_i2c_master(void)
{
	zassert_true(test_i2c_adv7513() == TC_PASS, NULL);
}

void test_main(void)
{
	ztest_test_suite(nios2_i2c_master_test,
			 ztest_unit_test(test_i2c_master));
	ztest_run_test_suite(nios2_i2c_master_test);
}
