/*
 * Copyright (C) 2012 Samsung Electronics
 *
 * Author: Donghwa Lee <dh09.lee@samsung.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <config.h>
#include <common.h>
#include <linux/err.h>
#include <asm/arch/cpu.h>
#include <asm/arch/dp_info.h>
#include <asm/arch/dp.h>
#include <fdtdec.h>
#include <libfdt.h>

/* Declare global data pointer */
DECLARE_GLOBAL_DATA_PTR;

struct exynos_dp *dp_regs;

void exynos_dp_set_base_addr(void)
{
#if CONFIG_IS_ENABLED(OF_CONTROL)
	unsigned int node = fdtdec_next_compatible(gd->fdt_blob,
					0, COMPAT_SAMSUNG_EXYNOS5_DP);
	if (node <= 0)
		debug("exynos_dp: Can't get device node for dp\n");

	dp_regs = (struct exynos_dp *)fdtdec_get_addr(gd->fdt_blob,
								node, "reg");
	if (dp_regs == NULL)
		debug("Can't get the DP base address\n");
#else
	dp_regs = (struct exynos_dp *)samsung_get_base_dp();
#endif
}

static void exynos_dp_enable_video_input(unsigned int enable)
{
	unsigned int reg;

	reg = readl(&dp_regs->video_ctl1);
	reg &= ~VIDEO_EN_MASK;

	/* enable video input*/
	if (enable)
		reg |= VIDEO_EN_MASK;

	writel(reg, &dp_regs->video_ctl1);

	return;
}

void exynos_dp_enable_video_bist(unsigned int enable)
{
	/*enable video bist*/
	unsigned int reg;

	reg = readl(&dp_regs->video_ctl4);
	reg &= ~VIDEO_BIST_MASK;

	/*enable video bist*/
	if (enable)
		reg |= VIDEO_BIST_MASK;

	writel(reg, &dp_regs->video_ctl4);

	return;
}

void exynos_dp_enable_video_mute(unsigned int enable)
{
	unsigned int reg;

	reg = readl(&dp_regs->video_ctl1);
	reg &= ~(VIDEO_MUTE_MASK);
	if (enable)
		reg |= VIDEO_MUTE_MASK;

	writel(reg, &dp_regs->video_ctl1);

	return;
}


static void exynos_dp_init_analog_param(void)
{
	unsigned int reg;

	/*
	 * Set termination
	 * Normal bandgap, Normal swing, Tx terminal registor 61 ohm
	 * 24M Phy clock, TX digital logic power is 100:1.0625V
	 */
	reg = SEL_BG_NEW_BANDGAP | TX_TERMINAL_CTRL_61_OHM |
		SWING_A_30PER_G_NORMAL;
	writel(reg, &dp_regs->analog_ctl1);

	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
	writel(reg, &dp_regs->analog_ctl2);

	/*
	 * Set power source for internal clk driver to 1.0625v.
	 * Select current reference of TX driver current to 00:Ipp/2+Ic/2.
	 * Set VCO range of PLL +- 0uA
	 */
	reg = DRIVE_DVDD_BIT_1_0625V | SEL_CURRENT_DEFAULT | VCO_BIT_000_MICRO;
	writel(reg, &dp_regs->analog_ctl3);

	/*
	 * Set AUX TX terminal resistor to 102 ohm
	 * Set AUX channel amplitude control
	*/
	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_52_OHM | TX_CUR1_2X | TX_CUR_4_MA;
	writel(reg, &dp_regs->pll_filter_ctl1);

	/*
	 * PLL loop filter bandwidth
	 * For 2.7Gbps: 175KHz, For 1.62Gbps: 234KHz
	 * PLL digital power select: 1.2500V
	 */
	reg = CH3_AMP_0_MV | CH2_AMP_0_MV | CH1_AMP_0_MV | CH0_AMP_0_MV;

	writel(reg, &dp_regs->amp_tuning_ctl);

	/*
	 * PLL loop filter bandwidth
	 * For 2.7Gbps: 175KHz, For 1.62Gbps: 234KHz
	 * PLL digital power select: 1.1250V
	 */
	reg = DP_PLL_LOOP_BIT_DEFAULT | DP_PLL_REF_BIT_1_1250V;
	writel(reg, &dp_regs->pll_ctl);
}

static void exynos_dp_init_interrupt(void)
{
	/* Set interrupt registers to initial states */

	/*
	 * Disable interrupt
	 * INT pin assertion polarity. It must be configured
	 * correctly according to ICU setting.
	 * 1 = assert high, 0 = assert low
	 */
	writel(INT_POL, &dp_regs->int_ctl);

	/* Clear pending regisers */
	writel(0xff, &dp_regs->common_int_sta1);
	writel(0xff, &dp_regs->common_int_sta2);
	writel(0xff, &dp_regs->common_int_sta3);
	writel(0xff, &dp_regs->common_int_sta4);
	writel(0xff, &dp_regs->int_sta);

	/* 0:mask,1: unmask */
	writel(0x00, &dp_regs->int_sta_mask1);
	writel(0x00, &dp_regs->int_sta_mask2);
	writel(0x00, &dp_regs->int_sta_mask3);
	writel(0x00, &dp_regs->int_sta_mask4);
	writel(0x00, &dp_regs->int_sta_mask);
}

void exynos_dp_reset(void)
{
	unsigned int reg_func_1;

	/*dp tx sw reset*/
	writel(RESET_DP_TX, &dp_regs->tx_sw_reset);

	exynos_dp_enable_video_input(DP_DISABLE);
	exynos_dp_enable_video_bist(DP_DISABLE);
	exynos_dp_enable_video_mute(DP_DISABLE);

	/* software reset */
	reg_func_1 = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
		HDCP_FUNC_EN_N | SW_FUNC_EN_N;

	writel(reg_func_1, &dp_regs->func_en1);
	writel(reg_func_1, &dp_regs->func_en2);

	mdelay(1);

	exynos_dp_init_analog_param();
	exynos_dp_init_interrupt();

	return;
}

void exynos_dp_enable_sw_func(unsigned int enable)
{
	unsigned int reg;

	reg = readl(&dp_regs->func_en1);
	reg &= ~(SW_FUNC_EN_N);

	if (!enable)
		reg |= SW_FUNC_EN_N;

	writel(reg, &dp_regs->func_en1);

	return;
}

unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable)
{
	unsigned int reg;

	reg = readl(&dp_regs->phy_pd);
	switch (block) {
	case AUX_BLOCK:
		reg &= ~(AUX_PD);
		if (enable)
			reg |= AUX_PD;
		break;
	case CH0_BLOCK:
		reg &= ~(CH0_PD);
		if (enable)
			reg |= CH0_PD;
		break;
	case CH1_BLOCK:
		reg &= ~(CH1_PD);
		if (enable)
			reg |= CH1_PD;
		break;
	case CH2_BLOCK:
		reg &= ~(CH2_PD);
		if (enable)
			reg |= CH2_PD;
		break;
	case CH3_BLOCK:
		reg &= ~(CH3_PD);
		if (enable)
			reg |= CH3_PD;
		break;
	case ANALOG_TOTAL:
		reg &= ~PHY_PD;
		if (enable)
			reg |= PHY_PD;
		break;
	case POWER_ALL:
		reg &= ~(PHY_PD | AUX_PD | CH0_PD | CH1_PD | CH2_PD |
			CH3_PD);
		if (enable)
			reg |= (PHY_PD | AUX_PD | CH0_PD | CH1_PD |
				CH2_PD | CH3_PD);
		break;
	default:
		printf("DP undefined block number : %d\n",  block);
		return -1;
	}

	writel(reg, &dp_regs->phy_pd);

	return 0;
}

unsigned int exynos_dp_get_pll_lock_status(void)
{
	unsigned int reg;

	reg = readl(&dp_regs->debug_ctl);

	if (reg & PLL_LOCK)
		return PLL_LOCKED;
	else
		return PLL_UNLOCKED;
}

static void exynos_dp_set_pll_power(unsigned int enable)
{
	unsigned int reg;

	reg = readl(&dp_regs->pll_ctl);
	reg &= ~(DP_PLL_PD);

	if (!enable)
		reg |= DP_PLL_PD;

	writel(reg, &dp_regs->pll_ctl);
}

int exynos_dp_init_analog_func(void)
{
	int ret = EXYNOS_DP_SUCCESS;
	unsigned int retry_cnt = 10;
	unsigned int reg;

	/*Power On All Analog block */
	exynos_dp_set_analog_power_down(POWER_ALL, DP_DISABLE);

	reg = PLL_LOCK_CHG;
	writel(reg, &dp_regs->common_int_sta1);

	reg = readl(&dp_regs->debug_ctl);
	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
	writel(reg, &dp_regs->debug_ctl);

	/*Assert DP PLL Reset*/
	reg = readl(&dp_regs->pll_ctl);
	reg |= DP_PLL_RESET;
	writel(reg, &dp_regs->pll_ctl);

	mdelay(1);

	/*Deassert DP PLL Reset*/
	reg = readl(&dp_regs->pll_ctl);
	reg &= ~(DP_PLL_RESET);
	writel(reg, &dp_regs->pll_ctl);

	exynos_dp_set_pll_power(DP_ENABLE);

	while (exynos_dp_get_pll_lock_status() == PLL_UNLOCKED) {
		mdelay(1);
		retry_cnt--;
		if (retry_cnt == 0) {
			printf("DP dp's pll lock failed : retry : %d\n",
					retry_cnt);
			return -EINVAL;
		}
	}

	debug("dp's pll lock success(%d)\n", retry_cnt);

	/* Enable Serdes FIFO function and Link symbol clock domain module */
	reg = readl(&dp_regs->func_en2);
	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
		| AUX_FUNC_EN_N);
	writel(reg, &dp_regs->func_en2);

	return ret;
}

void exynos_dp_init_hpd(void)
{
	unsigned int reg;

	/* Clear interrupts releated to Hot Plug Dectect */
	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
	writel(reg, &dp_regs->common_int_sta4);

	reg = INT_HPD;
	writel(reg, &dp_regs->int_sta);

	reg = readl(&dp_regs->sys_ctl3);
	reg &= ~(F_HPD | HPD_CTRL);
	writel(reg, &dp_regs->sys_ctl3);

	return;
}

static inline void exynos_dp_reset_aux(void)
{
	unsigned int reg;

	/* Disable AUX channel module */
	reg = readl(&dp_regs->func_en2);
	reg |= AUX_FUNC_EN_N;
	writel(reg, &dp_regs->func_en2);

	return;
}

void exynos_dp_init_aux(void)
{
	unsigned int reg;

	/* Clear inerrupts related to AUX channel */
	reg = RPLY_RECEIV | AUX_ERR;
	writel(reg, &dp_regs->int_sta);

	exynos_dp_reset_aux();

	/* Disable AUX transaction H/W retry */
	reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(3)|
		AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
	writel(reg, &dp_regs->aux_hw_retry_ctl);

	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
	writel(reg, &dp_regs->aux_ch_defer_ctl);

	/* Enable AUX channel module */
	reg = readl(&dp_regs->func_en2);
	reg &= ~AUX_FUNC_EN_N;
	writel(reg, &dp_regs->func_en2);

	return;
}

void exynos_dp_config_interrupt(void)
{
	unsigned int reg;

	/* 0: mask, 1: unmask */
	reg = COMMON_INT_MASK_1;
	writel(reg, &dp_regs->common_int_mask1);

	reg = COMMON_INT_MASK_2;
	writel(reg, &dp_regs->common_int_mask2);

	reg = COMMON_INT_MASK_3;
	writel(reg, &dp_regs->common_int_mask3);

	reg = COMMON_INT_MASK_4;
	writel(reg, &dp_regs->common_int_mask4);

	reg = INT_STA_MASK;
	writel(reg, &dp_regs->int_sta_mask);

	return;
}

unsigned int exynos_dp_get_plug_in_status(void)
{
	unsigned int reg;

	reg = readl(&dp_regs->sys_ctl3);
	if (reg & HPD_STATUS)
		return 0;

	return -1;
}

unsigned int exynos_dp_detect_hpd(void)
{
	int timeout_loop = DP_TIMEOUT_LOOP_COUNT;

	mdelay(2);

	while (exynos_dp_get_plug_in_status() != 0) {
		if (timeout_loop == 0)
			return -EINVAL;
		mdelay(10);
		timeout_loop--;
	}

	return EXYNOS_DP_SUCCESS;
}

unsigned int exynos_dp_start_aux_transaction(void)
{
	unsigned int reg;
	unsigned int ret = 0;
	unsigned int retry_cnt;

	/* Enable AUX CH operation */
	reg = readl(&dp_regs->aux_ch_ctl2);
	reg |= AUX_EN;
	writel(reg, &dp_regs->aux_ch_ctl2);

	retry_cnt = 10;
	while (retry_cnt) {
		reg = readl(&dp_regs->int_sta);
		if (!(reg & RPLY_RECEIV)) {
			if (retry_cnt == 0) {
				printf("DP Reply Timeout!!\n");
				ret = -EAGAIN;
				return ret;
			}
			mdelay(1);
			retry_cnt--;
		} else
			break;
	}

	/* Clear interrupt source for AUX CH command reply */
	writel(reg, &dp_regs->int_sta);

	/* Clear interrupt source for AUX CH access error */
	reg = readl(&dp_regs->int_sta);
	if (reg & AUX_ERR) {
		printf("DP Aux Access Error\n");
		writel(AUX_ERR, &dp_regs->int_sta);
		ret = -EAGAIN;
		return ret;
	}

	/* Check AUX CH error access status */
	reg = readl(&dp_regs->aux_ch_sta);
	if ((reg & AUX_STATUS_MASK) != 0) {
		debug("DP AUX CH error happens: %x\n", reg & AUX_STATUS_MASK);
		ret = -EAGAIN;
		return ret;
	}

	return EXYNOS_DP_SUCCESS;
}

unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr,
				unsigned char data)
{
	unsigned int reg, ret;

	/* Clear AUX CH data buffer */
	reg = BUF_CLR;
	writel(reg, &dp_regs->buffer_data_ctl);

	/* Select DPCD device address */
	reg = AUX_ADDR_7_0(reg_addr);
	writel(reg, &dp_regs->aux_addr_7_0);
	reg = AUX_ADDR_15_8(reg_addr);
	writel(reg, &dp_regs->aux_addr_15_8);
	reg = AUX_ADDR_19_16(reg_addr);
	writel(reg, &dp_regs->aux_addr_19_16);

	/* Write data buffer */
	reg = (unsigned int)data;
	writel(reg, &dp_regs->buf_data0);

	/*
	 * Set DisplayPort transaction and write 1 byte
	 * If bit 3 is 1, DisplayPort transaction.
	 * If Bit 3 is 0, I2C transaction.
	 */
	reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
	writel(reg, &dp_regs->aux_ch_ctl1);

	/* Start AUX transaction */
	ret = exynos_dp_start_aux_transaction();
	if (ret != EXYNOS_DP_SUCCESS) {
		printf("DP Aux transaction failed\n");
		return ret;
	}

	return ret;
}

unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr,
		unsigned char *data)
{
	unsigned int reg;
	int retval;

	/* Clear AUX CH data buffer */
	reg = BUF_CLR;
	writel(reg, &dp_regs->buffer_data_ctl);

	/* Select DPCD device address */
	reg = AUX_ADDR_7_0(reg_addr);
	writel(reg, &dp_regs->aux_addr_7_0);
	reg = AUX_ADDR_15_8(reg_addr);
	writel(reg, &dp_regs->aux_addr_15_8);
	reg = AUX_ADDR_19_16(reg_addr);
	writel(reg, &dp_regs->aux_addr_19_16);

	/*
	 * Set DisplayPort transaction and read 1 byte
	 * If bit 3 is 1, DisplayPort transaction.
	 * If Bit 3 is 0, I2C transaction.
	 */
	reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
	writel(reg, &dp_regs->aux_ch_ctl1);

	/* Start AUX transaction */
	retval = exynos_dp_start_aux_transaction();
	if (!retval)
		debug("DP Aux Transaction fail!\n");

	/* Read data buffer */
	reg = readl(&dp_regs->buf_data0);
	*data = (unsigned char)(reg & 0xff);

	return retval;
}

unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr,
				unsigned int count,
				unsigned char data[])
{
	unsigned int reg;
	unsigned int start_offset;
	unsigned int cur_data_count;
	unsigned int cur_data_idx;
	unsigned int retry_cnt;
	unsigned int ret = 0;

	/* Clear AUX CH data buffer */
	reg = BUF_CLR;
	writel(reg, &dp_regs->buffer_data_ctl);

	start_offset = 0;
	while (start_offset < count) {
		/* Buffer size of AUX CH is 16 * 4bytes */
		if ((count - start_offset) > 16)
			cur_data_count = 16;
		else
			cur_data_count = count - start_offset;

		retry_cnt = 5;
		while (retry_cnt) {
			/* Select DPCD device address */
			reg = AUX_ADDR_7_0(reg_addr + start_offset);
			writel(reg, &dp_regs->aux_addr_7_0);
			reg = AUX_ADDR_15_8(reg_addr + start_offset);
			writel(reg, &dp_regs->aux_addr_15_8);
			reg = AUX_ADDR_19_16(reg_addr + start_offset);
			writel(reg, &dp_regs->aux_addr_19_16);

			for (cur_data_idx = 0; cur_data_idx < cur_data_count;
					cur_data_idx++) {
				reg = data[start_offset + cur_data_idx];
				writel(reg, (unsigned int)&dp_regs->buf_data0 +
						(4 * cur_data_idx));
			}
			/*
			* Set DisplayPort transaction and write
			* If bit 3 is 1, DisplayPort transaction.
			* If Bit 3 is 0, I2C transaction.
			*/
			reg = AUX_LENGTH(cur_data_count) |
				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
			writel(reg, &dp_regs->aux_ch_ctl1);

			/* Start AUX transaction */
			ret = exynos_dp_start_aux_transaction();
			if (ret != EXYNOS_DP_SUCCESS) {
				if (retry_cnt == 0) {
					printf("DP Aux Transaction failed\n");
					return ret;
				}
				retry_cnt--;
			} else
				break;
		}
		start_offset += cur_data_count;
	}

	return ret;
}

unsigned int exynos_dp_read_bytes_from_dpcd(unsigned int reg_addr,
				unsigned int count,
				unsigned char data[])
{
	unsigned int reg;
	unsigned int start_offset;
	unsigned int cur_data_count;
	unsigned int cur_data_idx;
	unsigned int retry_cnt;
	unsigned int ret = 0;

	/* Clear AUX CH data buffer */
	reg = BUF_CLR;
	writel(reg, &dp_regs->buffer_data_ctl);

	start_offset = 0;
	while (start_offset < count) {
		/* Buffer size of AUX CH is 16 * 4bytes */
		if ((count - start_offset) > 16)
			cur_data_count = 16;
		else
			cur_data_count = count - start_offset;

		retry_cnt = 5;
		while (retry_cnt) {
			/* Select DPCD device address */
			reg = AUX_ADDR_7_0(reg_addr + start_offset);
			writel(reg, &dp_regs->aux_addr_7_0);
			reg = AUX_ADDR_15_8(reg_addr + start_offset);
			writel(reg, &dp_regs->aux_addr_15_8);
			reg = AUX_ADDR_19_16(reg_addr + start_offset);
			writel(reg, &dp_regs->aux_addr_19_16);
			/*
			 * Set DisplayPort transaction and read
			 * If bit 3 is 1, DisplayPort transaction.
			 * If Bit 3 is 0, I2C transaction.
			 */
			reg = AUX_LENGTH(cur_data_count) |
				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
			writel(reg, &dp_regs->aux_ch_ctl1);

			/* Start AUX transaction */
			ret = exynos_dp_start_aux_transaction();
			if (ret != EXYNOS_DP_SUCCESS) {
				if (retry_cnt == 0) {
					printf("DP Aux Transaction failed\n");
					return ret;
				}
				retry_cnt--;
			} else
				break;
		}

		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
				cur_data_idx++) {
			reg = readl((unsigned int)&dp_regs->buf_data0 +
					4 * cur_data_idx);
			data[start_offset + cur_data_idx] = (unsigned char)reg;
		}

		start_offset += cur_data_count;
	}

	return ret;
}

int exynos_dp_select_i2c_device(unsigned int device_addr,
				unsigned int reg_addr)
{
	unsigned int reg;
	int retval;

	/* Set EDID device address */
	reg = device_addr;
	writel(reg, &dp_regs->aux_addr_7_0);
	writel(0x0, &dp_regs->aux_addr_15_8);
	writel(0x0, &dp_regs->aux_addr_19_16);

	/* Set offset from base address of EDID device */
	writel(reg_addr, &dp_regs->buf_data0);

	/*
	 * Set I2C transaction and write address
	 * If bit 3 is 1, DisplayPort transaction.
	 * If Bit 3 is 0, I2C transaction.
	 */
	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
		AUX_TX_COMM_WRITE;
	writel(reg, &dp_regs->aux_ch_ctl1);

	/* Start AUX transaction */
	retval = exynos_dp_start_aux_transaction();
	if (retval != 0)
		printf("%s: DP Aux Transaction fail!\n", __func__);

	return retval;
}

int exynos_dp_read_byte_from_i2c(unsigned int device_addr,
				unsigned int reg_addr,
				unsigned int *data)
{
	unsigned int reg;
	int i;
	int retval;

	for (i = 0; i < 10; i++) {
		/* Clear AUX CH data buffer */
		reg = BUF_CLR;
		writel(reg, &dp_regs->buffer_data_ctl);

		/* Select EDID device */
		retval = exynos_dp_select_i2c_device(device_addr, reg_addr);
		if (retval != 0) {
			printf("DP Select EDID device fail. retry !\n");
			continue;
		}

		/*
		 * Set I2C transaction and read data
		 * If bit 3 is 1, DisplayPort transaction.
		 * If Bit 3 is 0, I2C transaction.
		 */
		reg = AUX_TX_COMM_I2C_TRANSACTION |
			AUX_TX_COMM_READ;
		writel(reg, &dp_regs->aux_ch_ctl1);

		/* Start AUX transaction */
		retval = exynos_dp_start_aux_transaction();
		if (retval != EXYNOS_DP_SUCCESS)
			printf("%s: DP Aux Transaction fail!\n", __func__);
	}

	/* Read data */
	if (retval == 0)
		*data = readl(&dp_regs->buf_data0);

	return retval;
}

int exynos_dp_read_bytes_from_i2c(unsigned int device_addr,
		unsigned int reg_addr, unsigned int count, unsigned char edid[])
{
	unsigned int reg;
	unsigned int i, j;
	unsigned int cur_data_idx;
	unsigned int defer = 0;
	int retval = 0;

	for (i = 0; i < count; i += 16) { /* use 16 burst */
		for (j = 0; j < 100; j++) {
			/* Clear AUX CH data buffer */
			reg = BUF_CLR;
			writel(reg, &dp_regs->buffer_data_ctl);

			/* Set normal AUX CH command */
			reg = readl(&dp_regs->aux_ch_ctl2);
			reg &= ~ADDR_ONLY;
			writel(reg, &dp_regs->aux_ch_ctl2);

			/*
			 * If Rx sends defer, Tx sends only reads
			 * request without sending addres
			 */
			if (!defer)
				retval =
					exynos_dp_select_i2c_device(device_addr,
							reg_addr + i);
			else
				defer = 0;

			if (retval == EXYNOS_DP_SUCCESS) {
				/*
				 * Set I2C transaction and write data
				 * If bit 3 is 1, DisplayPort transaction.
				 * If Bit 3 is 0, I2C transaction.
				 */
				reg = AUX_LENGTH(16) |
					AUX_TX_COMM_I2C_TRANSACTION |
					AUX_TX_COMM_READ;
				writel(reg, &dp_regs->aux_ch_ctl1);

				/* Start AUX transaction */
				retval = exynos_dp_start_aux_transaction();
				if (retval == 0)
					break;
				else
					printf("DP Aux Transaction fail!\n");
			}
			/* Check if Rx sends defer */
			reg = readl(&dp_regs->aux_rx_comm);
			if (reg == AUX_RX_COMM_AUX_DEFER ||
				reg == AUX_RX_COMM_I2C_DEFER) {
				printf("DP Defer: %d\n", reg);
				defer = 1;
			}
		}

		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
			reg = readl((unsigned int)&dp_regs->buf_data0
						 + 4 * cur_data_idx);
			edid[i + cur_data_idx] = (unsigned char)reg;
		}
	}

	return retval;
}

void exynos_dp_reset_macro(void)
{
	unsigned int reg;

	reg = readl(&dp_regs->phy_test);
	reg |= MACRO_RST;
	writel(reg, &dp_regs->phy_test);

	/* 10 us is the minimum Macro reset time. */
	mdelay(1);

	reg &= ~MACRO_RST;
	writel(reg, &dp_regs->phy_test);
}

void exynos_dp_set_link_bandwidth(unsigned char bwtype)
{
	unsigned int reg;

	reg = (unsigned int)bwtype;

	 /* Set bandwidth to 2.7G or 1.62G */
	if ((bwtype == DP_LANE_BW_1_62) || (bwtype == DP_LANE_BW_2_70))
		writel(reg, &dp_regs->link_bw_set);
}

unsigned char exynos_dp_get_link_bandwidth(void)
{
	unsigned char ret;
	unsigned int reg;

	reg = readl(&dp_regs->link_bw_set);
	ret = (unsigned char)reg;

	return ret;
}

void exynos_dp_set_lane_count(unsigned char count)
{
	unsigned int reg;

	reg = (unsigned int)count;

	if ((count == DP_LANE_CNT_1) || (count == DP_LANE_CNT_2) ||
			(count == DP_LANE_CNT_4))
		writel(reg, &dp_regs->lane_count_set);
}

unsigned int exynos_dp_get_lane_count(void)
{
	unsigned int reg;

	reg = readl(&dp_regs->lane_count_set);

	return reg;
}

unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt)
{
	unsigned int reg_list[DP_LANE_CNT_4] = {
		(unsigned int)&dp_regs->ln0_link_training_ctl,
		(unsigned int)&dp_regs->ln1_link_training_ctl,
		(unsigned int)&dp_regs->ln2_link_training_ctl,
		(unsigned int)&dp_regs->ln3_link_training_ctl,
	};

	return readl(reg_list[lanecnt]);
}

void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val,
		unsigned char lanecnt)
{
	unsigned int reg_list[DP_LANE_CNT_4] = {
		(unsigned int)&dp_regs->ln0_link_training_ctl,
		(unsigned int)&dp_regs->ln1_link_training_ctl,
		(unsigned int)&dp_regs->ln2_link_training_ctl,
		(unsigned int)&dp_regs->ln3_link_training_ctl,
	};

	writel(request_val, reg_list[lanecnt]);
}

void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt)
{
	unsigned char i;
	unsigned int reg;
	unsigned int reg_list[DP_LANE_CNT_4] = {
		(unsigned int)&dp_regs->ln0_link_training_ctl,
		(unsigned int)&dp_regs->ln1_link_training_ctl,
		(unsigned int)&dp_regs->ln2_link_training_ctl,
		(unsigned int)&dp_regs->ln3_link_training_ctl,
	};
	unsigned int reg_shift[DP_LANE_CNT_4] = {
		PRE_EMPHASIS_SET_0_SHIFT,
		PRE_EMPHASIS_SET_1_SHIFT,
		PRE_EMPHASIS_SET_2_SHIFT,
		PRE_EMPHASIS_SET_3_SHIFT
	};

	for (i = 0; i < lanecnt; i++) {
		reg = level << reg_shift[i];
		writel(reg, reg_list[i]);
	}
}

void exynos_dp_set_training_pattern(unsigned int pattern)
{
	unsigned int reg = 0;

	switch (pattern) {
	case PRBS7:
		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
		break;
	case D10_2:
		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
		break;
	case TRAINING_PTN1:
		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
		break;
	case TRAINING_PTN2:
		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
		break;
	case DP_NONE:
		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_DISABLE |
			SW_TRAINING_PATTERN_SET_NORMAL;
		break;
	default:
		break;
	}

	writel(reg, &dp_regs->training_ptn_set);
}

void exynos_dp_enable_enhanced_mode(unsigned char enable)
{
	unsigned int reg;

	reg = readl(&dp_regs->sys_ctl4);
	reg &= ~ENHANCED;

	if (enable)
		reg |= ENHANCED;

	writel(reg, &dp_regs->sys_ctl4);
}

void exynos_dp_enable_scrambling(unsigned int enable)
{
	unsigned int reg;

	reg = readl(&dp_regs->training_ptn_set);
	reg &= ~(SCRAMBLING_DISABLE);

	if (!enable)
		reg |= SCRAMBLING_DISABLE;

	writel(reg, &dp_regs->training_ptn_set);
}

int exynos_dp_init_video(void)
{
	unsigned int reg;

	/* Clear VID_CLK_CHG[1] and VID_FORMAT_CHG[3] and VSYNC_DET[7] */
	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
	writel(reg, &dp_regs->common_int_sta1);

	/* I_STRM__CLK detect : DE_CTL : Auto detect */
	reg &= ~DET_CTRL;
	writel(reg, &dp_regs->sys_ctl1);

	return 0;
}

void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info)
{
	unsigned int reg;

	/* Video Slave mode setting */
	reg = readl(&dp_regs->func_en1);
	reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
	reg |= MASTER_VID_FUNC_EN_N;
	writel(reg, &dp_regs->func_en1);

	/* Configure Interlaced for slave mode video */
	reg = readl(&dp_regs->video_ctl10);
	reg &= ~INTERACE_SCAN_CFG;
	reg |= (video_info->interlaced << INTERACE_SCAN_CFG_SHIFT);
	writel(reg, &dp_regs->video_ctl10);

	/* Configure V sync polarity for slave mode video */
	reg = readl(&dp_regs->video_ctl10);
	reg &= ~VSYNC_POLARITY_CFG;
	reg |= (video_info->v_sync_polarity << V_S_POLARITY_CFG_SHIFT);
	writel(reg, &dp_regs->video_ctl10);

	/* Configure H sync polarity for slave mode video */
	reg = readl(&dp_regs->video_ctl10);
	reg &= ~HSYNC_POLARITY_CFG;
	reg |= (video_info->h_sync_polarity << H_S_POLARITY_CFG_SHIFT);
	writel(reg, &dp_regs->video_ctl10);

	/*Set video mode to slave mode */
	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
	writel(reg, &dp_regs->soc_general_ctl);
}

void exynos_dp_set_video_color_format(struct edp_video_info *video_info)
{
	unsigned int reg;

	/* Configure the input color depth, color space, dynamic range */
	reg = (video_info->dynamic_range << IN_D_RANGE_SHIFT) |
		(video_info->color_depth << IN_BPC_SHIFT) |
		(video_info->color_space << IN_COLOR_F_SHIFT);
	writel(reg, &dp_regs->video_ctl2);

	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
	reg = readl(&dp_regs->video_ctl3);
	reg &= ~IN_YC_COEFFI_MASK;
	if (video_info->ycbcr_coeff)
		reg |= IN_YC_COEFFI_ITU709;
	else
		reg |= IN_YC_COEFFI_ITU601;
	writel(reg, &dp_regs->video_ctl3);
}

int exynos_dp_config_video_bist(struct edp_device_info *edp_info)
{
	unsigned int reg;
	unsigned int bist_type = 0;
	struct edp_video_info video_info = edp_info->video_info;

	/* For master mode, you don't need to set the video format */
	if (video_info.master_mode == 0) {
		writel(TOTAL_LINE_CFG_L(edp_info->disp_info.v_total),
				&dp_regs->total_ln_cfg_l);
		writel(TOTAL_LINE_CFG_H(edp_info->disp_info.v_total),
				&dp_regs->total_ln_cfg_h);
		writel(ACTIVE_LINE_CFG_L(edp_info->disp_info.v_res),
				&dp_regs->active_ln_cfg_l);
		writel(ACTIVE_LINE_CFG_H(edp_info->disp_info.v_res),
				&dp_regs->active_ln_cfg_h);
		writel(edp_info->disp_info.v_sync_width,
				&dp_regs->vsw_cfg);
		writel(edp_info->disp_info.v_back_porch,
				&dp_regs->vbp_cfg);
		writel(edp_info->disp_info.v_front_porch,
				&dp_regs->vfp_cfg);

		writel(TOTAL_PIXEL_CFG_L(edp_info->disp_info.h_total),
				&dp_regs->total_pix_cfg_l);
		writel(TOTAL_PIXEL_CFG_H(edp_info->disp_info.h_total),
				&dp_regs->total_pix_cfg_h);
		writel(ACTIVE_PIXEL_CFG_L(edp_info->disp_info.h_res),
				&dp_regs->active_pix_cfg_l);
		writel(ACTIVE_PIXEL_CFG_H(edp_info->disp_info.h_res),
				&dp_regs->active_pix_cfg_h);
		writel(H_F_PORCH_CFG_L(edp_info->disp_info.h_front_porch),
				&dp_regs->hfp_cfg_l);
		writel(H_F_PORCH_CFG_H(edp_info->disp_info.h_front_porch),
				&dp_regs->hfp_cfg_h);
		writel(H_SYNC_PORCH_CFG_L(edp_info->disp_info.h_sync_width),
				&dp_regs->hsw_cfg_l);
		writel(H_SYNC_PORCH_CFG_H(edp_info->disp_info.h_sync_width),
				&dp_regs->hsw_cfg_h);
		writel(H_B_PORCH_CFG_L(edp_info->disp_info.h_back_porch),
				&dp_regs->hbp_cfg_l);
		writel(H_B_PORCH_CFG_H(edp_info->disp_info.h_back_porch),
				&dp_regs->hbp_cfg_h);

		/*
		 * Set SLAVE_I_SCAN_CFG[2], VSYNC_P_CFG[1],
		 * HSYNC_P_CFG[0] properly
		 */
		reg = (video_info.interlaced << INTERACE_SCAN_CFG_SHIFT |
			video_info.v_sync_polarity << V_S_POLARITY_CFG_SHIFT |
			video_info.h_sync_polarity << H_S_POLARITY_CFG_SHIFT);
		writel(reg, &dp_regs->video_ctl10);
	}

	/* BIST color bar width set--set to each bar is 32 pixel width */
	switch (video_info.bist_pattern) {
	case COLORBAR_32:
		bist_type = BIST_WIDTH_BAR_32_PIXEL |
			  BIST_TYPE_COLOR_BAR;
		break;
	case COLORBAR_64:
		bist_type = BIST_WIDTH_BAR_64_PIXEL |
			  BIST_TYPE_COLOR_BAR;
		break;
	case WHITE_GRAY_BALCKBAR_32:
		bist_type = BIST_WIDTH_BAR_32_PIXEL |
			  BIST_TYPE_WHITE_GRAY_BLACK_BAR;
		break;
	case WHITE_GRAY_BALCKBAR_64:
		bist_type = BIST_WIDTH_BAR_64_PIXEL |
			  BIST_TYPE_WHITE_GRAY_BLACK_BAR;
		break;
	case MOBILE_WHITEBAR_32:
		bist_type = BIST_WIDTH_BAR_32_PIXEL |
			  BIST_TYPE_MOBILE_WHITE_BAR;
		break;
	case MOBILE_WHITEBAR_64:
		bist_type = BIST_WIDTH_BAR_64_PIXEL |
			  BIST_TYPE_MOBILE_WHITE_BAR;
		break;
	default:
		return -1;
	}

	reg = bist_type;
	writel(reg, &dp_regs->video_ctl4);

	return 0;
}

unsigned int exynos_dp_is_slave_video_stream_clock_on(void)
{
	unsigned int reg;

	/* Update Video stream clk detect status */
	reg = readl(&dp_regs->sys_ctl1);
	writel(reg, &dp_regs->sys_ctl1);

	reg = readl(&dp_regs->sys_ctl1);

	if (!(reg & DET_STA)) {
		debug("DP Input stream clock not detected.\n");
		return -EIO;
	}

	return EXYNOS_DP_SUCCESS;
}

void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value,
		unsigned int n_value)
{
	unsigned int reg;

	if (type == REGISTER_M) {
		reg = readl(&dp_regs->sys_ctl4);
		reg |= FIX_M_VID;
		writel(reg, &dp_regs->sys_ctl4);
		reg = M_VID0_CFG(m_value);
		writel(reg, &dp_regs->m_vid0);
		reg = M_VID1_CFG(m_value);
		writel(reg, &dp_regs->m_vid1);
		reg = M_VID2_CFG(m_value);
		writel(reg, &dp_regs->m_vid2);

		reg = N_VID0_CFG(n_value);
		writel(reg, &dp_regs->n_vid0);
		reg = N_VID1_CFG(n_value);
		writel(reg, &dp_regs->n_vid1);
		reg = N_VID2_CFG(n_value);
		writel(reg, &dp_regs->n_vid2);
	} else  {
		reg = readl(&dp_regs->sys_ctl4);
		reg &= ~FIX_M_VID;
		writel(reg, &dp_regs->sys_ctl4);
	}
}

void exynos_dp_set_video_timing_mode(unsigned int type)
{
	unsigned int reg;

	reg = readl(&dp_regs->video_ctl10);
	reg &= ~FORMAT_SEL;

	if (type != VIDEO_TIMING_FROM_CAPTURE)
		reg |= FORMAT_SEL;

	writel(reg, &dp_regs->video_ctl10);
}

void exynos_dp_enable_video_master(unsigned int enable)
{
	unsigned int reg;

	reg = readl(&dp_regs->soc_general_ctl);
	if (enable) {
		reg &= ~VIDEO_MODE_MASK;
		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
	} else {
		reg &= ~VIDEO_MODE_MASK;
		reg |= VIDEO_MODE_SLAVE_MODE;
	}

	writel(reg, &dp_regs->soc_general_ctl);
}

void exynos_dp_start_video(void)
{
	unsigned int reg;

	/* Enable Video input and disable Mute */
	reg = readl(&dp_regs->video_ctl1);
	reg |= VIDEO_EN;
	writel(reg, &dp_regs->video_ctl1);
}

unsigned int exynos_dp_is_video_stream_on(void)
{
	unsigned int reg;

	/* Update STRM_VALID */
	reg = readl(&dp_regs->sys_ctl3);
	writel(reg, &dp_regs->sys_ctl3);

	reg = readl(&dp_regs->sys_ctl3);
	if (!(reg & STRM_VALID))
		return -EIO;

	return EXYNOS_DP_SUCCESS;
}
