summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cpu/samsung/exynos5420/Makefile.inc3
-rw-r--r--src/cpu/samsung/exynos5420/clock_init.c26
-rw-r--r--src/cpu/samsung/exynos5420/cpu.c6
-rw-r--r--src/cpu/samsung/exynos5420/cpu.h1
-rw-r--r--src/cpu/samsung/exynos5420/dp-core.h260
-rw-r--r--src/cpu/samsung/exynos5420/dp-reg.c503
-rw-r--r--src/cpu/samsung/exynos5420/dp.c906
-rw-r--r--src/cpu/samsung/exynos5420/dp.h1778
-rw-r--r--src/cpu/samsung/exynos5420/dp_lowlevel.c1199
-rw-r--r--src/cpu/samsung/exynos5420/fb.c587
-rw-r--r--src/cpu/samsung/exynos5420/fimd.c450
-rw-r--r--src/cpu/samsung/exynos5420/fimd.h161
-rw-r--r--src/cpu/samsung/exynos5420/power.c2
-rw-r--r--src/cpu/samsung/exynos5420/power.h2
-rw-r--r--src/lib/edid.c10
-rw-r--r--src/mainboard/google/pit/mainboard.c121
16 files changed, 4157 insertions, 1858 deletions
diff --git a/src/cpu/samsung/exynos5420/Makefile.inc b/src/cpu/samsung/exynos5420/Makefile.inc
index 704a346209..4169a2efac 100644
--- a/src/cpu/samsung/exynos5420/Makefile.inc
+++ b/src/cpu/samsung/exynos5420/Makefile.inc
@@ -48,8 +48,7 @@ ramstage-y += monotonic_timer.c
ramstage-y += timer.c
ramstage-y += gpio.c
ramstage-y += i2c.c
-ramstage-y += dp-reg.c
-ramstage-y += fb.c
+ramstage-y += dp.c dp_lowlevel.c fimd.c
ramstage-y += usb.c
ramstage-y += cbmem.c
diff --git a/src/cpu/samsung/exynos5420/clock_init.c b/src/cpu/samsung/exynos5420/clock_init.c
index 2ce975cd1d..069fd8fdb7 100644
--- a/src/cpu/samsung/exynos5420/clock_init.c
+++ b/src/cpu/samsung/exynos5420/clock_init.c
@@ -30,7 +30,7 @@
void system_clock_init(void)
{
struct exynos5420_clock *clk =
- (struct exynos5420_clock *)EXYNOS5_CLOCK_BASE;
+ (struct exynos5420_clock *)EXYNOS5420_CLOCK_BASE;
struct exynos5_mct_regs *mct_regs =
(struct exynos5_mct_regs *)EXYNOS5_MULTI_CORE_TIMER_BASE;
u32 val;
@@ -49,6 +49,7 @@ void system_clock_init(void)
writel(IPLL_LOCK_VAL, &clk->ipll_lock);
writel(SPLL_LOCK_VAL, &clk->spll_lock);
writel(KPLL_LOCK_VAL, &clk->kpll_lock);
+ writel(RPLL_LOCK_VAL, &clk->rpll_lock);
setbits_le32(&clk->clk_src_cpu, MUX_HPM_SEL_MASK);
@@ -85,7 +86,7 @@ void system_clock_init(void)
/* Set DPLL */
writel(DPLL_CON1_VAL, &clk->dpll_con1);
- val = set_pll(0xc8, 0x2, 0x2);
+ val = set_pll(0x190, 0x4, 0x2);
writel(val, &clk->dpll_con0);
while ((readl(&clk->dpll_con0) & PLL_LOCKED) == 0)
;
@@ -133,6 +134,22 @@ void system_clock_init(void)
while ((readl(&clk->spll_con0) & PLL_LOCKED) == 0)
;
+ /* We use RPLL as the source for FIMD video stream clock */
+ writel(RPLL_CON1_VAL, &clk->rpll_con1);
+ writel(RPLL_CON2_VAL, &clk->rpll_con2);
+ /* computed by gabe from first principles; u-boot is probably
+ * wrong again
+ */
+ val = set_pll(0xa0, 0x3, 0x2);
+ writel(val, &clk->rpll_con0);
+ /* note: this is a meaningless exercise. The hardware lock
+ * detection does not work. So this just spins for some
+ * time and is done. NO indication of success should attach
+ * to this or any other spin on a con0 value.
+ */
+ while ((readl(&clk->rpll_con0) & PLL_LOCKED) == 0)
+ ;
+
writel(CLK_DIV_CDREX0_VAL, &clk->clk_div_cdrex0);
writel(CLK_DIV_CDREX1_VAL, &clk->clk_div_cdrex1);
@@ -194,8 +211,3 @@ void clock_gate(void)
{
/* Not implemented for now. */
}
-
-void clock_init_dp_clock(void)
-{
- /* Not implemented for now. */
-}
diff --git a/src/cpu/samsung/exynos5420/cpu.c b/src/cpu/samsung/exynos5420/cpu.c
index e95b438216..729e6b3707 100644
--- a/src/cpu/samsung/exynos5420/cpu.c
+++ b/src/cpu/samsung/exynos5420/cpu.c
@@ -26,8 +26,8 @@
#include <device/device.h>
#include <cbmem.h>
#include <arch/cache.h>
+#include "dp.h"
#include "fimd.h"
-#include "dp-core.h"
#include "cpu.h"
#include "clk.h"
#include "usb.h"
@@ -138,9 +138,7 @@ static void exynos_displayport_init(device_t dev, u32 lcdbase,
dcache_clean_invalidate_by_mva(lower, upper - lower);
mmu_config_range(lower / MiB, (upper - lower) / MiB, DCACHE_OFF);
- printk(BIOS_DEBUG, "Initializing Exynos LCD.\n");
-
- lcd_ctrl_init(fb_size, &panel, (void *)lcdbase);
+ mmio_resource(dev, 1, lcdbase/KiB, (fb_size + KiB - 1)/KiB);
}
static void cpu_enable(device_t dev)
diff --git a/src/cpu/samsung/exynos5420/cpu.h b/src/cpu/samsung/exynos5420/cpu.h
index 1cc6e6dd68..22ef8dbf40 100644
--- a/src/cpu/samsung/exynos5420/cpu.h
+++ b/src/cpu/samsung/exynos5420/cpu.h
@@ -197,6 +197,7 @@
#define samsung_get_base_clock() ((struct exynos5420_clock *)EXYNOS5_CLOCK_BASE)
#define samsung_get_base_ace_sfr() ((struct exynos5_ace_sfr *)EXYNOS5_ACE_SFR_BASE)
#define samsung_get_base_dsim() ((struct exynos5_dsim *)EXYNOS5_MIPI_DSI1_BASE)
+#define samsung_get_base_dp() ((struct exynos_dp *)EXYNOS5420_DP_BASE)
#define samsung_get_base_disp_ctrl() ((struct exynos5_disp_ctrl *)EXYNOS5_DISP1_CTRL_BASE)
#define samsung_get_base_fimd() ((struct exynos5_fimd *)EXYNOS5_FIMD_BASE)
#define samsung_get_base_pro_id() ((struct exynos5_pro_id *)EXYNOS5_PRO_ID)
diff --git a/src/cpu/samsung/exynos5420/dp-core.h b/src/cpu/samsung/exynos5420/dp-core.h
deleted file mode 100644
index 62144e3a26..0000000000
--- a/src/cpu/samsung/exynos5420/dp-core.h
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2013 Google Inc.
- * Copyright (C) 2012 Samsung Electronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/* Header file for Samsung DP (Display Port) interface driver. */
-
-#ifndef CPU_SAMSUNG_EXYNOS5420_DP_CORE_H
-#define CPU_SAMSUNG_EXYNOS5420_DP_CORE_H
-
-#define STREAM_ON_TIMEOUT 100
-#define PLL_LOCK_TIMEOUT 10
-#define DP_INIT_TRIES 10
-#define MAX_CR_LOOP 5
-#define MAX_EQ_LOOP 4
-
-/* Link tare type */
-enum link_rate {
- LINK_RATE_1_62GBPS = 0x06,
- LINK_RATE_2_70GBPS = 0x0a
-};
-
-/* Number of lanes supported */
-enum link_lane_count {
- LANE_COUNT1 = 1,
- LANE_COUNT2 = 2,
- LANE_COUNT4 = 4
-};
-
-/* Pre emphasis level */
-enum pre_emphasis_level {
- PRE_EMPHASIS_LEVEL_0,
- PRE_EMPHASIS_LEVEL_1,
- PRE_EMPHASIS_LEVEL_2,
- PRE_EMPHASIS_LEVEL_3,
-};
-
-/* Type of color space */
-enum color_space {
- COLOR_RGB,
- COLOR_YCBCR422,
- COLOR_YCBCR444
-};
-
-/* Video input Bit Per Color */
-enum color_depth {
- COLOR_6,
- COLOR_8,
- COLOR_10,
- COLOR_12
-};
-
-/* Type of YCbCr coefficient */
-enum color_coefficient {
- COLOR_YCBCR601,
- COLOR_YCBCR709
-};
-
-/* Color range */
-enum dynamic_range {
- VESA,
- CEA
-};
-
-/* Status of PLL clock */
-enum pll_status {
- PLL_UNLOCKED,
- PLL_LOCKED
-};
-
-/* To choose type of m_value */
-enum clock_recovery_m_value_type {
- CALCULATED_M,
- REGISTER_M
-};
-
-struct video_info {
- enum color_space color_space;
- enum dynamic_range dynamic_range;
- enum color_coefficient ycbcr_coeff;
- enum color_depth color_depth;
-
- enum link_rate link_rate;
- enum link_lane_count lane_count;
-
- char *name;
-
- unsigned int h_sync_polarity:1;
- unsigned int v_sync_polarity:1;
- unsigned int interlaced:1;
-};
-
-struct link_train {
- u8 link_rate;
- u8 lane_count;
-};
-
-struct s5p_dp_device {
- unsigned int irq;
- struct exynos5_dp *base;
- struct video_info *video_info;
- struct link_train link_train;
-};
-
-/* s5p_dp_reg.c */
-
-/*
- * Reset DP module
- *
- * param dp pointer to main s5p-dp structure
- */
-void s5p_dp_reset(struct s5p_dp_device *dp);
-/*
- * Initialize DP to recieve video stream
- *
- * param dp pointer to main s5p-dp structure
- */
-void s5p_dp_init_video(struct s5p_dp_device *dp);
-/*
- * Check whether PLL is locked
- *
- * param dp pointer to main s5p-dp structure
- * return Lock status
- */
-unsigned int s5p_dp_get_pll_lock_status(struct s5p_dp_device *dp);
-/*
- * Initialize analog functions of DP
- *
- * param dp pointer to main s5p-dp structure
- * return 0 on success
- */
-int s5p_dp_init_analog_func(struct s5p_dp_device *dp);
-/*
- * Initialize DP for AUX transaction
- *
- * param dp pointer to main s5p-dp structure
- */
-void s5p_dp_init_aux(struct s5p_dp_device *dp);
-
-/*
- * Start an AUX transaction.
- *
- * param dp pointer to main s5p-dp structure
- */
-int s5p_dp_start_aux_transaction(struct s5p_dp_device *dp);
-
-/*
- * Write a byte to DPCD register
- *
- * param dp pointer to main s5p-dp structure
- * param reg_addr DPCD register to be written
- * param data byte data to be written
- * return write status
- */
-int s5p_dp_write_byte_to_dpcd(struct s5p_dp_device *dp,
- unsigned int reg_addr,
- unsigned char data);
-/*
- * Read a byte from DPCD register
- *
- * param dp pointer to main s5p-dp structure
- * param reg_addr DPCD register to read
- * param data read byte data
- * return read status
- */
-int s5p_dp_read_byte_from_dpcd(struct s5p_dp_device *dp,
- unsigned int reg_addr,
- unsigned char *data);
-/*
- * Initialize DP video functions
- *
- * param dp pointer to main s5p-dp structure
- */
-//void s5p_dp_init_video(struct s5p_dp_device *dp);
-
-/*
- * Set color parameters for display
- *
- * param dp pointer to main s5p-dp structure
- * param color_depth Video input Bit Per Color
- * param color_space Colorimetric format of input video
- * param dynamic_range VESA range or CEA range
- * param coeff YCbCr Coefficients of input video
- */
-void s5p_dp_set_video_color_format(struct s5p_dp_device *dp,
- unsigned int color_depth,
- unsigned int color_space,
- unsigned int dynamic_range,
- unsigned int coeff);
-/*
- * Check whether video clock is on
- *
- * param dp pointer to main s5p-dp structure
- * return clock status
- */
-int s5p_dp_is_slave_video_stream_clock_on(struct s5p_dp_device *dp);
-/*
- * Check whether video clock is on
- *
- * param dp pointer to main s5p-dp structure
- * param type clock_recovery_m_value_type
- * param m_value to caluculate m_vid value
- * param n_value to caluculate n_vid value
- */
-void s5p_dp_set_video_cr_mn(struct s5p_dp_device *dp,
- enum clock_recovery_m_value_type type,
- unsigned int m_value,
- unsigned int n_value);
-/*
- * Set DP to video slave mode thereby enabling video master
- *
- * param dp pointer to main s5p-dp structure
- */
-void s5p_dp_enable_video_master(struct s5p_dp_device *dp);
-/*
- * Check whether video stream is on
- *
- * param dp pointer to main s5p-dp structure
- * return video stream status
- */
-int s5p_dp_is_video_stream_on(struct s5p_dp_device *dp);
-/*
- * Configure DP in slave mode
- *
- * param dp pointer to main s5p-dp structure
- * param video_info pointer to main video_info structure.
- */
-void s5p_dp_config_video_slave_mode(struct s5p_dp_device *dp,
- struct video_info *video_info);
-
-/*
- * Wait unitl HW link training done
- *
- * param dp pointer to main s5p-dp structure
- */
-void s5p_dp_wait_hw_link_training_done(struct s5p_dp_device *dp);
-
-/* startup and init */
-struct exynos5_fimd_panel;
-void fb_init(unsigned long int fb_size, void *lcdbase,
- struct exynos5_fimd_panel *pd);
-int dp_controller_init(struct s5p_dp_device *dp_device);
-int lcd_ctrl_init(unsigned long int fb_size,
- struct exynos5_fimd_panel *panel_data, void *lcdbase);
-#endif /* CPU_SAMSUNG_EXYNOS5420_DP_CORE_H */
diff --git a/src/cpu/samsung/exynos5420/dp-reg.c b/src/cpu/samsung/exynos5420/dp-reg.c
deleted file mode 100644
index 1d6a6b1d55..0000000000
--- a/src/cpu/samsung/exynos5420/dp-reg.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Samsung Electronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/* Samsung DP (Display port) register interface driver. */
-
-#include <console/console.h>
-#include <arch/io.h>
-#include <delay.h>
-#include <timer.h>
-#include "clk.h"
-#include "cpu.h"
-#include "periph.h"
-#include "dp.h"
-#include "fimd.h"
-#include "dp-core.h"
-
-void s5p_dp_reset(struct s5p_dp_device *dp)
-{
- u32 reg;
- struct exynos5_dp *base = dp->base;
-
- writel(RESET_DP_TX, &base->dp_tx_sw_reset);
-
- /* Stop Video */
- clrbits_le32(&base->video_ctl_1, VIDEO_EN);
- clrbits_le32(&base->video_ctl_1, HDCP_VIDEO_MUTE);
-
- reg = 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, &base->func_en_1);
-
- reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
- SERDES_FIFO_FUNC_EN_N |
- LS_CLK_DOMAIN_FUNC_EN_N;
- writel(reg, &base->func_en_2);
-
- udelay(20);
-
- reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
- LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
-
- writel(reg, &base->lane_map);
-
- writel(0x0, &base->sys_ctl_1);
- writel(0x40, &base->sys_ctl_2);
- writel(0x0, &base->sys_ctl_3);
- writel(0x0, &base->sys_ctl_4);
-
- writel(0x0, &base->pkt_send_ctl);
- writel(0x0, &base->dp_hdcp_ctl);
-
- writel(0x5e, &base->dp_hpd_deglitch_l);
- writel(0x1a, &base->dp_hpd_deglitch_h);
-
- writel(0x10, &base->dp_debug_ctl);
-
- writel(0x0, &base->dp_phy_test);
-
- writel(0x0, &base->dp_video_fifo_thrd);
- writel(0x20, &base->dp_audio_margin);
-
- writel(0x4, &base->m_vid_gen_filter_th);
- writel(0x2, &base->m_aud_gen_filter_th);
-
- writel(0x00000101, &base->soc_general_ctl);
-
- /* Set Analog Parameters */
- writel(0x10, &base->analog_ctl_1);
- writel(0x0C, &base->analog_ctl_2);
- writel(0x85, &base->analog_ctl_3);
- writel(0x66, &base->pll_filter_ctl_1);
- writel(0x0, &base->tx_amp_tuning_ctl);
-
- /* Set interrupt pin assertion polarity as high */
- writel(INT_POL0 | INT_POL1, &base->int_ctl);
-
- /* Clear pending regisers */
- writel(0xff, &base->common_int_sta_1);
- writel(0x4f, &base->common_int_sta_2);
- writel(0xe0, &base->common_int_sta_3);
- writel(0xe7, &base->common_int_sta_4);
- writel(0x63, &base->dp_int_sta);
-
- /* 0:mask,1: unmask */
- writel(0x00, &base->common_int_mask_1);
- writel(0x00, &base->common_int_mask_2);
- writel(0x00, &base->common_int_mask_3);
- writel(0x00, &base->common_int_mask_4);
- writel(0x00, &base->int_sta_mask);
-}
-
-unsigned int s5p_dp_get_pll_lock_status(struct s5p_dp_device *dp)
-{
- u32 reg;
-
- reg = readl(&dp->base->dp_debug_ctl);
- if (reg & PLL_LOCK)
- return PLL_LOCKED;
- else
- return PLL_UNLOCKED;
-}
-
-int s5p_dp_init_analog_func(struct s5p_dp_device *dp)
-{
- u32 reg;
- struct mono_time current, end;
- struct exynos5_dp *base = dp->base;
-
- writel(0x00, &base->dp_phy_pd);
-
- reg = PLL_LOCK_CHG;
- writel(reg, &base->common_int_sta_1);
-
- clrbits_le32(&base->dp_debug_ctl, (F_PLL_LOCK | PLL_LOCK_CTRL));
-
- /* Power up PLL */
- if (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-
- clrbits_le32(&base->dp_pll_ctl, DP_PLL_PD);
-
- timer_monotonic_get(&current);
- end = current;
- mono_time_add_msecs(&end, PLL_LOCK_TIMEOUT);
-
- while (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
- if (mono_time_after(&current, &end)) {
- printk(BIOS_ERR, "%s: PLL is not locked\n",
- __func__);
- return -1;
- }
- timer_monotonic_get(&current);
- }
- }
-
- /* Enable Serdes FIFO function and Link symbol clock domain module */
- clrbits_le32(&base->func_en_2, (SERDES_FIFO_FUNC_EN_N |
- LS_CLK_DOMAIN_FUNC_EN_N | AUX_FUNC_EN_N));
- return 0;
-}
-
-void s5p_dp_init_aux(struct s5p_dp_device *dp)
-{
- u32 reg;
- struct exynos5_dp *base = dp->base;
-
- /* Clear inerrupts related to AUX channel */
- reg = RPLY_RECEIV | AUX_ERR;
- writel(reg, &base->dp_int_sta);
-
- /* Disable AUX channel module */
- setbits_le32(&base->func_en_2, AUX_FUNC_EN_N);
-
- /* Disable AUX transaction H/W retry */
- reg = (3 & AUX_BIT_PERIOD_MASK) << AUX_BIT_PERIOD_SHIFT;
- reg |= (0 & AUX_HW_RETRY_COUNT_MASK) << AUX_HW_RETRY_COUNT_SHIFT;
- reg |= (AUX_HW_RETRY_INTERVAL_600_US << AUX_HW_RETRY_INTERVAL_SHIFT);
- writel(reg, &base->aux_hw_retry_ctl) ;
-
- /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
- reg = DEFER_CTRL_EN;
- reg |= (1 & DEFER_COUNT_MASK) << DEFER_COUNT_SHIFT;
- writel(reg, &base->aux_ch_defer_dtl);
-
- /* Enable AUX channel module */
- clrbits_le32(&base->func_en_2, AUX_FUNC_EN_N);
-}
-
-int s5p_dp_start_aux_transaction(struct s5p_dp_device *dp)
-{
- int reg;
- struct exynos5_dp *base = dp->base;
-
- /* Enable AUX CH operation */
- setbits_le32(&base->aux_ch_ctl_2, AUX_EN);
-
- /* Is AUX CH command reply received? */
- reg = readl(&base->dp_int_sta);
- while (!(reg & RPLY_RECEIV))
- reg = readl(&base->dp_int_sta);
-
- /* Clear interrupt source for AUX CH command reply */
- writel(RPLY_RECEIV, &base->dp_int_sta);
-
- /* Clear interrupt source for AUX CH access error */
- reg = readl(&base->dp_int_sta);
- if (reg & AUX_ERR) {
- printk(BIOS_ERR, "%s: AUX_ERR encountered, dp_int_sta: "
- "0x%02x\n", __func__, reg);
- writel(AUX_ERR, &base->dp_int_sta);
- return -1;
- }
-
- /* Check AUX CH error access status */
- reg = readl(&base->dp_int_sta);
- if ((reg & AUX_STATUS_MASK) != 0) {
- printk(BIOS_ERR, "AUX CH error happens: %d\n\n",
- reg & AUX_STATUS_MASK);
- return -1;
- }
-
- return 0;
-}
-
-int s5p_dp_write_byte_to_dpcd(struct s5p_dp_device *dp,
- unsigned int reg_addr,
- unsigned char data)
-{
- u32 reg;
- int i;
- int retval;
- struct exynos5_dp *base = dp->base;
-
- for (i = 0; i < MAX_AUX_RETRY_COUNT; i++) {
- /* Clear AUX CH data buffer */
- writel(BUF_CLR, &base->buf_data_ctl);
-
- /* Select DPCD device address */
- reg = reg_addr >> AUX_ADDR_7_0_SHIFT;
- reg &= AUX_ADDR_7_0_MASK;
- writel(reg, &base->aux_addr_7_0);
- reg = reg_addr >> AUX_ADDR_15_8_SHIFT;
- reg &= AUX_ADDR_15_8_MASK;
- writel(reg, &base->aux_addr_15_8);
- reg = reg_addr >> AUX_ADDR_19_16_SHIFT;
- reg &= AUX_ADDR_19_16_MASK;
- writel(reg, &base->aux_addr_19_16);
-
- /* Write data buffer */
- reg = (unsigned int)data;
- writel(reg, &base->buf_data_0);
-
- /*
- * 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, &base->aux_ch_ctl_1);
-
- /* Start AUX transaction */
- retval = s5p_dp_start_aux_transaction(dp);
- if (retval == 0)
- break;
- else
- printk(BIOS_DEBUG, "Aux Transaction fail!\n");
- }
-
- return retval;
-}
-
-int s5p_dp_read_byte_from_dpcd(struct s5p_dp_device *dp,
- unsigned int reg_addr,
- unsigned char *data)
-{
- u32 reg;
- int i;
- int retval;
- struct exynos5_dp *base = dp->base;
-
- for (i = 0; i < MAX_AUX_RETRY_COUNT; i++) {
- /* Clear AUX CH data buffer */
- writel(BUF_CLR, &base->buf_data_ctl);
-
- /* Select DPCD device address */
- reg = reg_addr >> AUX_ADDR_7_0_SHIFT;
- reg &= AUX_ADDR_7_0_MASK;
- writel(reg, &base->aux_addr_7_0);
- reg = reg_addr >> AUX_ADDR_15_8_SHIFT;
- reg &= AUX_ADDR_15_8_MASK;
- writel(reg, &base->aux_addr_15_8);
- reg = reg_addr >> AUX_ADDR_19_16_SHIFT;
- reg &= AUX_ADDR_19_16_MASK;
- writel(reg, &base->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, &base->aux_ch_ctl_1);
-
- /* Start AUX transaction */
- retval = s5p_dp_start_aux_transaction(dp);
- if (retval == 0)
- break;
- else
- printk(BIOS_DEBUG, "Aux Transaction fail!\n");
- }
-
- /* Read data buffer */
- if (!retval) {
- reg = readl(&base->buf_data_0);
- *data = (unsigned char)(reg & 0xff);
- }
-
- return retval;
-}
-
-void s5p_dp_init_video(struct s5p_dp_device *dp)
-{
- u32 reg;
- struct exynos5_dp *base = dp->base;
-
- reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
- writel(reg, &base->common_int_sta_1);
-
- reg = 0x0;
- writel(reg, &base->sys_ctl_1);
-
- reg = (4 & CHA_CRI_MASK) << CHA_CRI_SHIFT;
- reg |= CHA_CTRL;
- writel(reg, &base->sys_ctl_2);
-
- reg = 0x0;
- writel(reg, &base->sys_ctl_3);
-}
-
-void s5p_dp_set_video_color_format(struct s5p_dp_device *dp,
- unsigned int color_depth,
- unsigned int color_space,
- unsigned int dynamic_range,
- unsigned int coeff)
-{
- u32 reg;
- struct exynos5_dp *base = dp->base;
-
- /* Configure the input color depth, color space, dynamic range */
- reg = (dynamic_range << IN_D_RANGE_SHIFT) |
- (color_depth << IN_BPC_SHIFT) |
- (color_space << IN_COLOR_F_SHIFT);
- writel(reg, &base->video_ctl_2);
-
- /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
- reg = readl(&base->video_ctl_3);
- reg &= ~IN_YC_COEFFI_MASK;
- if (coeff)
- reg |= IN_YC_COEFFI_ITU709;
- else
- reg |= IN_YC_COEFFI_ITU601;
- writel(reg, &base->video_ctl_3);
-}
-
-int s5p_dp_is_slave_video_stream_clock_on(struct s5p_dp_device *dp)
-{
- u32 reg;
- struct exynos5_dp *base = dp->base;
-
- reg = readl(&base->sys_ctl_1);
- writel(reg, &base->sys_ctl_1);
-
- reg = readl(&base->sys_ctl_1);
-
- if (!(reg & DET_STA))
- return -1;
-
- reg = readl(&base->sys_ctl_2);
- writel(reg, &base->sys_ctl_2);
-
- reg = readl(&base->sys_ctl_2);
-
- if (reg & CHA_STA) {
- printk(BIOS_DEBUG, "Input stream clk is changing\n");
- return -1;
- }
-
- return 0;
-}
-
-void s5p_dp_set_video_cr_mn(struct s5p_dp_device *dp,
- enum clock_recovery_m_value_type type,
- unsigned int m_value,
- unsigned int n_value)
-{
- u32 reg;
- struct exynos5_dp *base = dp->base;
-
- if (type == REGISTER_M) {
- setbits_le32(&base->sys_ctl_4, FIX_M_VID);
-
- reg = m_value >> M_VID_0_VALUE_SHIFT;
- writel(reg, &base->m_vid_0);
-
- reg = (m_value >> M_VID_1_VALUE_SHIFT);
- writel(reg, &base->m_vid_1);
-
- reg = (m_value >> M_VID_2_VALUE_SHIFT);
- writel(reg, &base->m_vid_2);
-
- reg = n_value >> N_VID_0_VALUE_SHIFT;
- writel(reg, &base->n_vid_0);
-
- reg = (n_value >> N_VID_1_VALUE_SHIFT);
- writel(reg, &base->n_vid_1);
-
- reg = (n_value >> N_VID_2_VALUE_SHIFT);
- writel(reg, &base->n_vid_2);
- } else {
- clrbits_le32(&base->sys_ctl_4, FIX_M_VID);
-
- writel(0x00, &base->n_vid_0);
- writel(0x80, &base->n_vid_1);
- writel(0x00, &base->n_vid_2);
- }
-}
-
-void s5p_dp_enable_video_master(struct s5p_dp_device *dp)
-{
- u32 reg;
- struct exynos5_dp *base = dp->base;
-
- reg = readl(&base->soc_general_ctl);
- reg &= ~VIDEO_MODE_MASK;
- reg |= VIDEO_MODE_SLAVE_MODE;
- writel(reg, &base->soc_general_ctl);
-}
-
-int s5p_dp_is_video_stream_on(struct s5p_dp_device *dp)
-{
- u32 reg, i = 0;
- struct mono_time current, end;
- struct exynos5_dp *base = dp->base;
-
- /* Wait for 4 VSYNC_DET interrupts */
- timer_monotonic_get(&current);
- end = current;
- mono_time_add_msecs(&end, STREAM_ON_TIMEOUT);
-
- do {
- reg = readl(&base->common_int_sta_1);
- if (reg & VSYNC_DET) {
- i++;
- writel(reg | VSYNC_DET, &base->common_int_sta_1);
- }
- if (i == 4)
- break;
- timer_monotonic_get(&current);
- } while (mono_time_before(&current, &end));
-
- if (i != 4) {
- printk(BIOS_DEBUG, "s5p_dp_is_video_stream_on timeout\n");
- return -1;
- }
-
- return 0;
-}
-
-void s5p_dp_config_video_slave_mode(struct s5p_dp_device *dp,
- struct video_info *video_info)
-{
- u32 reg;
- struct exynos5_dp *base = dp->base;
-
- reg = readl(&base->func_en_1);
- reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
- reg |= MASTER_VID_FUNC_EN_N;
- writel(reg, &base->func_en_1);
-
- reg = readl(&base->video_ctl_10);
- reg &= ~INTERACE_SCAN_CFG;
- reg |= (video_info->interlaced << 2);
- writel(reg, &base->video_ctl_10);
-
- reg = readl(&base->video_ctl_10);
- reg &= ~VSYNC_POLARITY_CFG;
- reg |= (video_info->v_sync_polarity << 1);
- writel(reg, &base->video_ctl_10);
-
- reg = readl(&base->video_ctl_10);
- reg &= ~HSYNC_POLARITY_CFG;
- reg |= (video_info->h_sync_polarity << 0);
- writel(reg, &base->video_ctl_10);
-
- reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
- writel(reg, &base->soc_general_ctl);
-}
-
-void s5p_dp_wait_hw_link_training_done(struct s5p_dp_device *dp)
-{
- u32 reg;
- struct exynos5_dp *base = dp->base;
-
- reg = readl(&base->dp_hw_link_training);
- while (reg & HW_TRAINING_EN)
- reg = readl(&base->dp_hw_link_training);
-}
diff --git a/src/cpu/samsung/exynos5420/dp.c b/src/cpu/samsung/exynos5420/dp.c
new file mode 100644
index 0000000000..a1c69c5b57
--- /dev/null
+++ b/src/cpu/samsung/exynos5420/dp.c
@@ -0,0 +1,906 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * Author: Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <arch/io.h>
+#include <stdlib.h>
+#include <string.h>
+#include <timer.h>
+#include <delay.h>
+#include <console/console.h>
+#include <lib.h>
+#include "timer.h"
+#include "cpu.h"
+#include "power.h"
+#include "sysreg.h"
+#include <drivers/maxim/max77686/max77686.h>
+
+#include "device/i2c.h"
+#include "i2c.h"
+#include "fimd.h"
+#include "dp.h"
+
+/*
+ * Here is the rough outline of how we bring up the display:
+ * 1. Upon power-on Sink generates a hot plug detection pulse thru HPD
+ * 2. Source determines video mode by reading DPCD receiver capability field
+ * (DPCD 00000h to 0000Dh) including eDP CP capability register (DPCD
+ * 0000Dh).
+ * 3. Sink replies DPCD receiver capability field.
+ * 4. Source starts EDID read thru I2C-over-AUX.
+ * 5. Sink replies EDID thru I2C-over-AUX.
+ * 6. Source determines link configuration, such as MAX_LINK_RATE and
+ * MAX_LANE_COUNT. Source also determines which type of eDP Authentication
+ * method to use and writes DPCD link configuration field (DPCD 00100h to
+ * 0010Ah) including eDP configuration set (DPCD 0010Ah).
+ * 7. Source starts link training. Sink does clock recovery and equalization.
+ * 8. Source reads DPCD link status field (DPCD 00200h to 0020Bh).
+ * 9. Sink replies DPCD link status field. If main link is not stable, Source
+ * repeats Step 7.
+ * 10. Source sends MSA (Main Stream Attribute) data. Sink extracts video
+ * parameters and recovers stream clock.
+ * 11. Source sends video data.
+ */
+
+
+static int exynos_dp_init_dp(void)
+{
+ int ret;
+ exynos_dp_reset();
+
+ /* SW defined function Normal operation */
+ exynos_dp_enable_sw_func(DP_ENABLE);
+
+ ret = exynos_dp_init_analog_func();
+ if (ret != EXYNOS_DP_SUCCESS)
+ return ret;
+
+ exynos_dp_init_hpd();
+ exynos_dp_init_aux();
+
+ return ret;
+}
+
+static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
+{
+ int i;
+ unsigned char sum = 0;
+
+ for (i = 0; i < EDID_BLOCK_LENGTH; i++)
+ sum = sum + edid_data[i];
+
+ return sum;
+}
+
+static unsigned int exynos_dp_read_edid(void)
+{
+ unsigned char edid[EDID_BLOCK_LENGTH * 2];
+ unsigned int extend_block = 0;
+ unsigned char sum;
+ unsigned char test_vector;
+ int retval = 0;
+
+ /*
+ * EDID device address is 0x50.
+ * However, if necessary, you must have set upper address
+ * into E-EDID in I2C device, 0x30.
+ */
+
+ /* Read Extension Flag, Number of 128-byte EDID extension blocks */
+ if (exynos_dp_read_byte_from_i2c
+ (I2C_EDID_DEVICE_ADDR, EDID_EXTENSION_FLAG, &extend_block))
+ return -1;
+
+ if (extend_block > 0) {
+ /* Read EDID data */
+ retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR,
+ EDID_HEADER_PATTERN,
+ EDID_BLOCK_LENGTH,
+ &edid[EDID_HEADER_PATTERN]);
+
+ if (retval != 0) {
+ printk(BIOS_ERR, "DP EDID Read failed!\n");
+ return -1;
+ }
+ sum = exynos_dp_calc_edid_check_sum(edid);
+ if (sum != 0) {
+ printk(BIOS_ERR, "DP EDID bad checksum!\n");
+ return -1;
+ }
+ /* Read additional EDID data */
+ retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR,
+ EDID_BLOCK_LENGTH,
+ EDID_BLOCK_LENGTH,
+ &edid[EDID_BLOCK_LENGTH]);
+ if (retval != 0) {
+ printk(BIOS_ERR, "DP EDID Read failed!\n");
+ return -1;
+ }
+ sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
+ if (sum != 0) {
+ printk(BIOS_ERR, "DP EDID bad checksum!\n");
+ return -1;
+ }
+ exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST,
+ &test_vector);
+ if (test_vector & DPCD_TEST_EDID_READ) {
+ exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM,
+ edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
+ exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE,
+ DPCD_TEST_EDID_CHECKSUM_WRITE);
+ }
+ } else {
+ /* Read EDID data */
+ retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR,
+ EDID_HEADER_PATTERN,
+ EDID_BLOCK_LENGTH,
+ &edid[EDID_HEADER_PATTERN]);
+
+ if (retval != 0) {
+ printk(BIOS_ERR, "DP EDID Read failed!\n");
+ return -1;
+ }
+ sum = exynos_dp_calc_edid_check_sum(edid);
+ if (sum != 0) {
+ printk(BIOS_ERR, "DP EDID bad checksum!\n");
+ return -1;
+ }
+
+ exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST,
+ &test_vector);
+ if (test_vector & DPCD_TEST_EDID_READ) {
+ exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM,
+ edid[EDID_CHECKSUM]);
+ exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE,
+ DPCD_TEST_EDID_CHECKSUM_WRITE);
+ }
+
+ }
+
+ return 0;
+}
+
+static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info)
+{
+ unsigned char buf[12];
+ unsigned int ret;
+ unsigned char temp;
+ unsigned char retry_cnt;
+ unsigned char dpcd_rev[16];
+ unsigned char lane_bw[16];
+ unsigned char lane_cnt[16];
+
+ memset(dpcd_rev, 0, sizeof(dpcd_rev));
+ memset(lane_bw, 0, sizeof(lane_bw));
+ memset(lane_cnt, 0, sizeof(lane_cnt));
+ memset(buf, 0, sizeof(buf));
+
+ retry_cnt = 5;
+ while (retry_cnt) {
+ /* Read DPCD 0x0000-0x000b */
+ ret = exynos_dp_read_bytes_from_dpcd(DPCD_DPCD_REV, 12,
+ buf);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ if (retry_cnt == 0) {
+ printk(BIOS_ERR, "DP read_byte_from_dpcd() failed\n");
+ return ret;
+ }
+ retry_cnt--;
+ } else
+ break;
+ }
+ /* */
+ temp = buf[DPCD_DPCD_REV];
+ if (temp == DP_DPCD_REV_10 || temp == DP_DPCD_REV_11)
+ edp_info->dpcd_rev = temp;
+ else {
+ printk(BIOS_ERR, "DP Wrong DPCD Rev : %x\n", temp);
+ return -1;
+ }
+ temp = buf[DPCD_MAX_LINK_RATE];
+ if (temp == DP_LANE_BW_1_62 || temp == DP_LANE_BW_2_70)
+ edp_info->lane_bw = temp;
+ else {
+ printk(BIOS_ERR, "DP Wrong MAX LINK RATE : %x\n", temp);
+ return -1;
+ }
+ /*Refer VESA Display Port Stnadard Ver1.1a Page 120 */
+ if (edp_info->dpcd_rev == DP_DPCD_REV_11) {
+ temp = buf[DPCD_MAX_LANE_COUNT] & 0x1f;
+ if (buf[DPCD_MAX_LANE_COUNT] & 0x80)
+ edp_info->dpcd_efc = 1;
+ else
+ edp_info->dpcd_efc = 0;
+ } else {
+ temp = buf[DPCD_MAX_LANE_COUNT];
+ edp_info->dpcd_efc = 0;
+ }
+
+ if (temp == DP_LANE_CNT_1 || temp == DP_LANE_CNT_2 ||
+ temp == DP_LANE_CNT_4) {
+ edp_info->lane_cnt = temp;
+ } else {
+ printk(BIOS_ERR, "DP Wrong MAX LANE COUNT : %x\n", temp);
+ return -1;
+ }
+
+ ret = exynos_dp_read_edid();
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP exynos_dp_read_edid() failed\n");
+ return -1;
+ }
+
+ return ret;
+}
+
+static void exynos_dp_init_training(void)
+{
+ /*
+ * MACRO_RST must be applied after the PLL_LOCK to avoid
+ * the DP inter pair skew issue for at least 10 us
+ */
+ exynos_dp_reset_macro();
+
+ /* All DP analog module power up */
+ exynos_dp_set_analog_power_down(POWER_ALL, 0);
+}
+
+static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info)
+{
+ unsigned char buf[5];
+ unsigned int ret;
+
+ edp_info->lt_info.lt_status = DP_LT_CR;
+ edp_info->lt_info.ep_loop = 0;
+ edp_info->lt_info.cr_loop[0] = 0;
+ edp_info->lt_info.cr_loop[1] = 0;
+ edp_info->lt_info.cr_loop[2] = 0;
+ edp_info->lt_info.cr_loop[3] = 0;
+
+ /* Set sink to D0 (Sink Not Ready) mode. */
+ ret = exynos_dp_write_byte_to_dpcd(DPCD_SINK_POWER_STATE,
+ DPCD_SET_POWER_STATE_D0);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP write_dpcd_byte failed\n");
+ return ret;
+ }
+
+ /* Set link rate and count as you want to establish*/
+ exynos_dp_set_link_bandwidth(edp_info->lane_bw);
+ exynos_dp_set_lane_count(edp_info->lane_cnt);
+
+ /* Setup RX configuration */
+ buf[0] = edp_info->lane_bw;
+ buf[1] = edp_info->lane_cnt;
+
+ ret = exynos_dp_write_bytes_to_dpcd(DPCD_LINK_BW_SET, 2,
+ buf);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP write_dpcd_byte failed\n");
+ return ret;
+ }
+
+ exynos_dp_set_lane_pre_emphasis(PRE_EMPHASIS_LEVEL_0,
+ edp_info->lane_cnt);
+
+ /* Set training pattern 1 */
+ exynos_dp_set_training_pattern(TRAINING_PTN1);
+
+ /* Set RX training pattern */
+ buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1;
+
+ buf[1] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 |
+ DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0;
+ buf[2] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 |
+ DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0;
+ buf[3] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 |
+ DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0;
+ buf[4] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 |
+ DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0;
+
+ ret = exynos_dp_write_bytes_to_dpcd(DPCD_TRAINING_PATTERN_SET,
+ 5, buf);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP write_dpcd_byte failed\n");
+ return ret;
+ }
+ return ret;
+}
+
+static unsigned int exynos_dp_training_pattern_dis(void)
+{
+ unsigned int ret;
+
+ exynos_dp_set_training_pattern(DP_NONE);
+
+ ret = exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET,
+ DPCD_TRAINING_PATTERN_DISABLED);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP requst_link_traninig_req failed\n");
+ return -1;
+ }
+
+ return ret;
+}
+
+static unsigned int exynos_dp_enable_rx_to_enhanced_mode(unsigned char enable)
+{
+ unsigned char data;
+ unsigned int ret;
+
+ ret = exynos_dp_read_byte_from_dpcd(DPCD_LANE_COUNT_SET,
+ &data);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP read_from_dpcd failed\n");
+ return -1;
+ }
+
+ if (enable)
+ data = DPCD_ENHANCED_FRAME_EN | DPCD_LN_COUNT_SET(data);
+ else
+ data = DPCD_LN_COUNT_SET(data);
+
+ ret = exynos_dp_write_byte_to_dpcd(DPCD_LANE_COUNT_SET,
+ data);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP write_to_dpcd failed\n");
+ return -1;
+
+ }
+
+ return ret;
+}
+
+static unsigned int exynos_dp_set_enhanced_mode(unsigned char enhance_mode)
+{
+ unsigned int ret;
+
+ ret = exynos_dp_enable_rx_to_enhanced_mode(enhance_mode);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP rx_enhance_mode failed\n");
+ return -1;
+ }
+
+ exynos_dp_enable_enhanced_mode(enhance_mode);
+
+ return ret;
+}
+
+static int exynos_dp_read_dpcd_lane_stat(struct edp_device_info *edp_info,
+ unsigned char *status)
+{
+ unsigned int ret, i;
+ unsigned char buf[2];
+ unsigned char lane_stat[DP_LANE_CNT_4] = {0,};
+ const unsigned char shift_val[] = {0, 4, 0, 4};
+
+ ret = exynos_dp_read_bytes_from_dpcd(DPCD_LANE0_1_STATUS, 2, buf);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP read lane status failed\n");
+ return ret;
+ }
+
+ for (i = 0; i < edp_info->lane_cnt; i++) {
+ lane_stat[i] = (buf[(i / 2)] >> shift_val[i]) & 0x0f;
+ if (lane_stat[0] != lane_stat[i]) {
+ printk(BIOS_ERR, "Wrong lane status\n");
+ return -1;
+ }
+ }
+
+ *status = lane_stat[0];
+
+ return ret;
+}
+
+static unsigned int exynos_dp_read_dpcd_adj_req(unsigned char lane_num,
+ unsigned char *sw, unsigned char *em)
+{
+ const unsigned char shift_val[] = {0, 4, 0, 4};
+ unsigned int ret;
+ unsigned char buf;
+ unsigned int dpcd_addr;
+
+ /*lane_num value is used as arry index, so this range 0 ~ 3 */
+ dpcd_addr = DPCD_ADJUST_REQUEST_LANE0_1 + (lane_num / 2);
+
+ ret = exynos_dp_read_byte_from_dpcd(dpcd_addr, &buf);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP read adjust request failed\n");
+ return -1;
+ }
+
+ *sw = ((buf >> shift_val[lane_num]) & 0x03);
+ *em = ((buf >> shift_val[lane_num]) & 0x0c) >> 2;
+
+ return ret;
+}
+
+static int exynos_dp_equalizer_err_link(struct edp_device_info *edp_info)
+{
+ int ret;
+
+ ret = exynos_dp_training_pattern_dis();
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP training_patter_disable() failed\n");
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ }
+
+ ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP set_enhanced_mode() failed\n");
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ }
+
+ return ret;
+}
+
+static int exynos_dp_reduce_link_rate(struct edp_device_info *edp_info)
+{
+ int ret;
+
+ if (edp_info->lane_bw == DP_LANE_BW_2_70) {
+ edp_info->lane_bw = DP_LANE_BW_1_62;
+ printk(BIOS_ERR, "DP Change lane bw to 1.62Gbps\n");
+ edp_info->lt_info.lt_status = DP_LT_START;
+ ret = EXYNOS_DP_SUCCESS;
+ } else {
+ ret = exynos_dp_training_pattern_dis();
+ if (ret != EXYNOS_DP_SUCCESS)
+ printk(BIOS_ERR, "DP training_patter_disable() failed\n");
+
+ ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc);
+ if (ret != EXYNOS_DP_SUCCESS)
+ printk(BIOS_ERR, "DP set_enhanced_mode() failed\n");
+
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ }
+
+ return ret;
+}
+
+static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info
+ *edp_info)
+{
+ unsigned int ret;
+ unsigned char lane_stat;
+ unsigned char lt_ctl_val[DP_LANE_CNT_4] = {0, };
+ unsigned int i;
+ unsigned char adj_req_sw;
+ unsigned char adj_req_em;
+ unsigned char buf[5];
+
+ mdelay(1);
+
+ ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP read lane status failed\n");
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ return ret;
+ }
+
+ if (lane_stat & DP_LANE_STAT_CR_DONE) {
+ printk(BIOS_DEBUG,"DP clock Recovery training succeed\n");
+ exynos_dp_set_training_pattern(TRAINING_PTN2);
+
+ for (i = 0; i < edp_info->lane_cnt; i++) {
+ ret = exynos_dp_read_dpcd_adj_req(i, &adj_req_sw,
+ &adj_req_em);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ return ret;
+ }
+
+ lt_ctl_val[i] = 0;
+ lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw;
+
+ if ((adj_req_sw == VOLTAGE_LEVEL_3)
+ || (adj_req_em == PRE_EMPHASIS_LEVEL_3)) {
+ lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 |
+ MAX_PRE_EMPHASIS_REACH_3;
+ }
+ exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i);
+ }
+
+ buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_2;
+ buf[1] = lt_ctl_val[0];
+ buf[2] = lt_ctl_val[1];
+ buf[3] = lt_ctl_val[2];
+ buf[4] = lt_ctl_val[3];
+
+ ret = exynos_dp_write_bytes_to_dpcd(
+ DPCD_TRAINING_PATTERN_SET, 5, buf);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP write training pattern1 failed\n");
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ return ret;
+ } else
+ edp_info->lt_info.lt_status = DP_LT_ET;
+ } else {
+ for (i = 0; i < edp_info->lane_cnt; i++) {
+ lt_ctl_val[i] = exynos_dp_get_lanex_pre_emphasis(i);
+ ret = exynos_dp_read_dpcd_adj_req(i,
+ &adj_req_sw, &adj_req_em);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP read adj req failed\n");
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ return ret;
+ }
+
+ if ((adj_req_sw == VOLTAGE_LEVEL_3) ||
+ (adj_req_em == PRE_EMPHASIS_LEVEL_3))
+ ret = exynos_dp_reduce_link_rate(edp_info);
+
+ if ((DRIVE_CURRENT_SET_0_GET(lt_ctl_val[i]) ==
+ adj_req_sw) &&
+ (PRE_EMPHASIS_SET_0_GET(lt_ctl_val[i]) ==
+ adj_req_em)) {
+ edp_info->lt_info.cr_loop[i]++;
+ if (edp_info->lt_info.cr_loop[i] == MAX_CR_LOOP)
+ ret = exynos_dp_reduce_link_rate(
+ edp_info);
+ }
+
+ lt_ctl_val[i] = 0;
+ lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw;
+
+ if ((adj_req_sw == VOLTAGE_LEVEL_3) ||
+ (adj_req_em == PRE_EMPHASIS_LEVEL_3)) {
+ lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 |
+ MAX_PRE_EMPHASIS_REACH_3;
+ }
+ exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i);
+ }
+
+ ret = exynos_dp_write_bytes_to_dpcd(
+ DPCD_TRAINING_LANE0_SET, 4, lt_ctl_val);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP write training pattern2 failed\n");
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info
+ *edp_info)
+{
+ unsigned int ret;
+ unsigned char lane_stat, adj_req_sw, adj_req_em, i;
+ unsigned char lt_ctl_val[DP_LANE_CNT_4] = {0,};
+ unsigned char interlane_aligned = 0;
+ unsigned char f_bw;
+ unsigned char f_lane_cnt;
+ unsigned char sink_stat;
+
+ mdelay(1);
+
+ ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP read lane status failed\n");
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ return ret;
+ }
+
+ printk(BIOS_DEBUG,"DP lane stat : %x\n", lane_stat);
+
+ if (lane_stat & DP_LANE_STAT_CR_DONE) {
+ printk(BIOS_DEBUG, "DP_LANE_STAT_CR_DONE ok\n");
+ ret = exynos_dp_read_byte_from_dpcd(DPCD_LN_ALIGN_UPDATED,
+ &sink_stat);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ printk(BIOS_ERR, "DP read DPCD_LN_ALIGN_UPDATED failed\n");
+ return ret;
+ }
+
+ interlane_aligned = (sink_stat & DPCD_INTERLANE_ALIGN_DONE);
+ printk(BIOS_DEBUG, "interlane_aligned: %d\n", interlane_aligned);
+ printk(BIOS_DEBUG, "Check %d lanes\n", edp_info->lane_cnt);
+
+ for (i = 0; i < edp_info->lane_cnt; i++) {
+ ret = exynos_dp_read_dpcd_adj_req(i,
+ &adj_req_sw, &adj_req_em);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP read adj req 1 failed\n");
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+
+ return ret;
+ }
+
+ lt_ctl_val[i] = 0;
+ lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw;
+
+ if ((adj_req_sw == VOLTAGE_LEVEL_3) ||
+ (adj_req_em == PRE_EMPHASIS_LEVEL_3)) {
+ lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3;
+ lt_ctl_val[i] |= MAX_PRE_EMPHASIS_REACH_3;
+ }
+ }
+
+ if (((lane_stat&DP_LANE_STAT_CE_DONE) &&
+ (lane_stat&DP_LANE_STAT_SYM_LOCK))
+ && (interlane_aligned == DPCD_INTERLANE_ALIGN_DONE)) {
+ printk(BIOS_DEBUG,"DP Equalizer training succeed\n");
+
+ f_bw = exynos_dp_get_link_bandwidth();
+ f_lane_cnt = exynos_dp_get_lane_count();
+
+ printk(BIOS_DEBUG,"DP final BandWidth : %x\n", f_bw);
+ printk(BIOS_DEBUG,"DP final Lane Count : %x\n", f_lane_cnt);
+
+ edp_info->lt_info.lt_status = DP_LT_FINISHED;
+
+ exynos_dp_equalizer_err_link(edp_info);
+
+ } else {
+ edp_info->lt_info.ep_loop++;
+
+ if (edp_info->lt_info.ep_loop > MAX_EQ_LOOP) {
+ if (edp_info->lane_bw == DP_LANE_BW_2_70) {
+ ret = exynos_dp_reduce_link_rate(
+ edp_info);
+ } else {
+ edp_info->lt_info.lt_status =
+ DP_LT_FAIL;
+ exynos_dp_equalizer_err_link(edp_info);
+ }
+ } else {
+ for (i = 0; i < edp_info->lane_cnt; i++)
+ exynos_dp_set_lanex_pre_emphasis(
+ lt_ctl_val[i], i);
+
+ ret = exynos_dp_write_bytes_to_dpcd(
+ DPCD_TRAINING_LANE0_SET,
+ 4, lt_ctl_val);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP set lt pattern failed\n");
+ edp_info->lt_info.lt_status =
+ DP_LT_FAIL;
+ exynos_dp_equalizer_err_link(edp_info);
+ }
+ }
+ }
+ } else if (edp_info->lane_bw == DP_LANE_BW_2_70) {
+ ret = exynos_dp_reduce_link_rate(edp_info);
+ } else {
+ edp_info->lt_info.lt_status = DP_LT_FAIL;
+ exynos_dp_equalizer_err_link(edp_info);
+ }
+
+ return ret;
+}
+
+static unsigned int exynos_dp_sw_link_training(struct edp_device_info *edp_info)
+{
+ /* the C compiler is almost smart enough to know this gets set.
+ * But not quite.
+ */
+ unsigned int ret = 0;
+ int training_finished;
+
+ /* Turn off unnecessary lane */
+ if (edp_info->lane_cnt == 1)
+ exynos_dp_set_analog_power_down(CH1_BLOCK, 1);
+
+ training_finished = 0;
+
+ edp_info->lt_info.lt_status = DP_LT_START;
+
+ /* Process here */
+ while (!training_finished) {
+ switch (edp_info->lt_info.lt_status) {
+ case DP_LT_START:
+ ret = exynos_dp_link_start(edp_info);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP LT:link start failed\n");
+ training_finished = 1;
+ }
+ break;
+ case DP_LT_CR:
+ ret = exynos_dp_process_clock_recovery(edp_info);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP LT:clock recovery failed\n");
+ training_finished = 1;
+ }
+ break;
+ case DP_LT_ET:
+ ret = exynos_dp_process_equalizer_training(edp_info);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP LT:equalizer training failed\n");
+ training_finished = 1;
+ }
+ break;
+ case DP_LT_FINISHED:
+ training_finished = 1;
+ break;
+ case DP_LT_FAIL:
+ printk(BIOS_ERR,"DP: %s: DP_LT_FAIL: failed\n", __func__);
+ training_finished = 1;
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+static unsigned int exynos_dp_set_link_train(struct edp_device_info *edp_info)
+{
+ unsigned int ret;
+
+ exynos_dp_init_training();
+
+ ret = exynos_dp_sw_link_training(edp_info);
+ if (ret != EXYNOS_DP_SUCCESS)
+ printk(BIOS_ERR, "DP dp_sw_link_traning() failed\n");
+
+ return ret;
+}
+
+static void exynos_dp_enable_scramble(unsigned int enable)
+{
+ unsigned char data;
+
+ if (enable) {
+ exynos_dp_enable_scrambling(DP_ENABLE);
+
+ exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET,
+ &data);
+ exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET,
+ (u8)(data & ~DPCD_SCRAMBLING_DISABLED));
+ } else {
+ exynos_dp_enable_scrambling(DP_DISABLE);
+ exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET,
+ &data);
+ exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET,
+ (u8)(data | DPCD_SCRAMBLING_DISABLED));
+ }
+}
+
+static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info)
+{
+ unsigned int ret = 0;
+ unsigned int retry_cnt;
+
+ mdelay(1);
+
+ if (edp_info->video_info.master_mode) {
+ printk(BIOS_ERR,
+ "DP does not support master mode: bailing out\n");
+ return -1;
+ } else {
+ /* debug slave */
+ exynos_dp_config_video_slave_mode(&edp_info->video_info);
+ }
+
+ exynos_dp_set_video_color_format(&edp_info->video_info);
+
+ ret = exynos_dp_get_pll_lock_status();
+ if (ret != PLL_LOCKED) {
+ printk(BIOS_ERR, "DP PLL is not locked yet\n");
+ return -1;
+ }
+
+ if (edp_info->video_info.master_mode == 0) {
+ retry_cnt = 10;
+ while (retry_cnt) {
+ ret = exynos_dp_is_slave_video_stream_clock_on();
+ if (ret != EXYNOS_DP_SUCCESS) {
+ if (retry_cnt == 0) {
+ printk(BIOS_ERR, "DP stream_clock_on failed\n");
+ return ret;
+ }
+ retry_cnt--;
+ mdelay(1);
+ } else {
+ printk(BIOS_DEBUG, "DP stream_clock succeeds\n");
+ break;
+ }
+ }
+ }
+
+ /* Set to use the register calculated M/N video */
+ exynos_dp_set_video_cr_mn(CALCULATED_M, 0, 0);
+
+ /* For video bist, Video timing must be generated by register
+ * not clear if we still need this. We could take it out and it
+ * might appear to work, then fail strangely.
+ */
+ exynos_dp_set_video_timing_mode(VIDEO_TIMING_FROM_CAPTURE);
+
+ /* we need to be sure this is off. */
+ exynos_dp_disable_video_bist();
+
+ /* Disable video mute */
+ exynos_dp_enable_video_mute(DP_DISABLE);
+
+ /* Configure video Master or Slave mode */
+ exynos_dp_enable_video_master(edp_info->video_info.master_mode);
+
+ /* Enable video */
+ exynos_dp_start_video();
+
+ if (edp_info->video_info.master_mode == 0) {
+ retry_cnt = 100;
+ while (retry_cnt) {
+ ret = exynos_dp_is_video_stream_on();
+ if (ret != EXYNOS_DP_SUCCESS) {
+ retry_cnt--;
+ if (retry_cnt == 0) {
+ printk(BIOS_ERR, "DP Timeout of video stream\n");
+ }
+ } else {
+ printk(BIOS_DEBUG, "DP video stream is on\n");
+ break;
+ }
+ mdelay(5);
+ }
+ }
+
+ return ret;
+}
+
+int exynos_init_dp(struct edp_device_info *edp_info)
+{
+ unsigned int ret;
+
+
+ dp_phy_control(1);
+
+ ret = exynos_dp_init_dp();
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP exynos_dp_init_dp() failed\n");
+ return ret;
+ }
+
+ ret = exynos_dp_handle_edid(edp_info);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "EDP handle_edid fail\n");
+ return ret;
+ }
+
+ ret = exynos_dp_set_link_train(edp_info);
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP link training fail\n");
+ return ret;
+ }
+ printk(BIOS_DEBUG, "EDP link training ok\n");
+
+ exynos_dp_enable_scramble(DP_ENABLE);
+ exynos_dp_enable_rx_to_enhanced_mode(DP_ENABLE);
+ exynos_dp_enable_enhanced_mode(DP_ENABLE);
+
+ exynos_dp_set_link_bandwidth(edp_info->lane_bw);
+ exynos_dp_set_lane_count(edp_info->lane_cnt);
+
+ exynos_dp_init_video();
+ ret = exynos_dp_config_video(edp_info);
+
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "Exynos DP init failed\n");
+ return ret;
+ }
+ printk(BIOS_DEBUG, "Exynos DP init done\n");
+
+ return ret;
+}
+
diff --git a/src/cpu/samsung/exynos5420/dp.h b/src/cpu/samsung/exynos5420/dp.h
index 46579b3594..d260c88af1 100644
--- a/src/cpu/samsung/exynos5420/dp.h
+++ b/src/cpu/samsung/exynos5420/dp.h
@@ -24,474 +24,1402 @@
#define CPU_SAMSUNG_EXYNOS5420_DP_H
/* DSIM register map */
-struct exynos5_dp {
+struct exynos_dp {
u8 res1[0x10];
- u32 dp_tx_version;
- u32 dp_tx_sw_reset;
- u32 func_en_1;
- u32 func_en_2;
- u32 video_ctl_1;
- u32 video_ctl_2;
- u32 video_ctl_3;
- u32 video_ctl_4;
- u32 clr_blue_cb;
- u32 clr_green_y;
- u32 clr_red_cr;
- u32 video_ctl_8;
+ u32 tx_version;
+ u32 tx_sw_reset;
+ u32 func_en1;
+ u32 func_en2;
+ u32 video_ctl1;
+ u32 video_ctl2;
+ u32 video_ctl3;
+ u32 video_ctl4;
+ u32 color_blue_cb;
+ u32 color_green_y;
+ u32 color_red_cr;
+ u32 video_ctl8;
u8 res2[0x4];
- u32 video_ctl_10;
- u32 total_line_l;
- u32 total_line_h;
- u32 active_line_l;
- u32 active_line_h;
- u32 v_f_porch;
- u32 vsync;
- u32 v_b_porch;
- u32 total_pixel_l;
- u32 total_pixel_h;
- u32 active_pixel_l;
- u32 active_pixel_h;
- u32 h_f_porch_l;
- u32 h_f_porch_h;
- u32 hsync_l;
- u32 hysnc_h;
- u32 h_b_porch_l;
- u32 h_b_porch_h;
- u32 vid_status;
- u32 total_line_sta_l;
- u32 total_line_sta_h;
- u32 active_line_sta_l;
- u32 active_line_sta_h;
- u32 v_f_porch_sta;
- u32 vsync_sta;
- u32 v_b_porch_sta;
- u32 total_pixel_sta_l;
- u32 total_pixel_sta_h;
- u32 active_pixel_sta_l;
- u32 active_pixel_sta_h;
- u32 h_f_porch_sta_l;
- u32 h_f_porch_sta_h;
- u32 hsync_sta_l;
- u32 hsync_sta_h;
- u32 h_b_porch_sta_l;
- u32 h_b_porch__sta_h;
+ u32 video_ctl10;
+ u32 total_ln_cfg_l;
+ u32 total_ln_cfg_h;
+ u32 active_ln_cfg_l;
+ u32 active_ln_cfg_h;
+ u32 vfp_cfg;
+ u32 vsw_cfg;
+ u32 vbp_cfg;
+ u32 total_pix_cfg_l;
+ u32 total_pix_cfg_h;
+ u32 active_pix_cfg_l;
+ u32 active_pix_cfg_h;
+ u32 hfp_cfg_l;
+ u32 hfp_cfg_h;
+ u32 hsw_cfg_l;
+ u32 hsw_cfg_h;
+ u32 hbp_cfg_l;
+ u32 hbp_cfg_h;
+ u32 video_status;
+ u32 total_ln_sta_l;
+ u32 total_ln_sta_h;
+ u32 active_ln_sta_l;
+ u32 active_ln_sta_h;
+
+ u32 vfp_sta;
+ u32 vsw_sta;
+ u32 vbp_sta;
+
+ u32 total_pix_sta_l;
+ u32 total_pix_sta_h;
+ u32 active_pix_sta_l;
+ u32 active_pix_sta_h;
+
+ u32 hfp_sta_l;
+ u32 hfp_sta_h;
+ u32 hsw_sta_l;
+ u32 hsw_sta_h;
+ u32 hbp_sta_l;
+ u32 hbp_sta_h;
+
u8 res3[0x288];
+
u32 lane_map;
u8 res4[0x10];
- u32 analog_ctl_1;
- u32 analog_ctl_2;
- u32 analog_ctl_3;
- u32 pll_filter_ctl_1;
- u32 tx_amp_tuning_ctl;
+ u32 analog_ctl1;
+ u32 analog_ctl2;
+ u32 analog_ctl3;
+
+ u32 pll_filter_ctl1;
+ u32 amp_tuning_ctl;
u8 res5[0xc];
+
u32 aux_hw_retry_ctl;
u8 res6[0x2c];
u32 int_state;
- u32 common_int_sta_1;
- u32 common_int_sta_2;
- u32 common_int_sta_3;
- u32 common_int_sta_4;
+ u32 common_int_sta1;
+ u32 common_int_sta2;
+ u32 common_int_sta3;
+ u32 common_int_sta4;
u8 res7[0x8];
- u32 dp_int_sta;
- u32 common_int_mask_1;
- u32 common_int_mask_2;
- u32 common_int_mask_3;
- u32 common_int_mask_4;
- u8 res8[0x08];
- u32 int_sta_mask;
+
+ u32 int_sta;
+ u8 res8[0x1c];
u32 int_ctl;
u8 res9[0x200];
- u32 sys_ctl_1;
- u32 sys_ctl_2;
- u32 sys_ctl_3;
- u32 sys_ctl_4;
- u32 dp_vid_ctl;
+ u32 sys_ctl1;
+ u32 sys_ctl2;
+ u32 sys_ctl3;
+ u32 sys_ctl4;
+ u32 vid_ctl;
u8 res10[0x2c];
u32 pkt_send_ctl;
- u8 res11[0x4];
- u32 dp_hdcp_ctl;
- u8 res12[0x34];
+ u8 res[0x4];
+ u32 hdcp_ctl;
+ u8 res11[0x34];
u32 link_bw_set;
+
u32 lane_count_set;
- u32 dp_training_ptn_set;
- u32 ln0_link_trn_ctl;
- u32 ln1_link_trn_ctl;
- u32 ln2_link_trn_ctl;
- u32 ln3_link_trn_ctl;
- u32 dp_dn_spread;
- u32 dp_hw_link_training;
- u8 res13[0x1c];
- u32 dp_debug_ctl;
- u32 dp_hpd_deglitch_l;
- u32 dp_hpd_deglitch_h;
- u8 res14[0x14];
- u32 dp_link_debug_ctl;
- u8 res15[0x1c];
- u32 m_vid_0;
- u32 m_vid_1;
- u32 m_vid_2;
- u32 n_vid_0;
- u32 n_vid_1;
- u32 n_vid_2;
+ u32 training_ptn_set;
+ u32 ln0_link_training_ctl;
+ u32 ln1_link_training_ctl;
+ u32 ln2_link_training_ctl;
+ u32 ln3_link_training_ctl;
+ u32 dn_spread_ctl;
+ u32 hw_link_training_ctl;
+ u8 res12[0x1c];
+
+ u32 debug_ctl;
+ u32 hpd_deglitch_l;
+ u32 hpd_deglitch_h;
+
+ u8 res13[0x14];
+ u32 link_debug_ctl;
+
+ u8 res14[0x1c];
+
+ u32 m_vid0;
+ u32 m_vid1;
+ u32 m_vid2;
+ u32 n_vid0;
+ u32 n_vid1;
+ u32 n_vid2;
u32 m_vid_mon;
- u32 dp_pll_ctl;
- u32 dp_phy_pd;
- u32 dp_phy_test;
+ u32 pll_ctl;
+ u32 phy_pd;
+ u32 phy_test;
+ u8 res15[0x8];
+
+ u32 video_fifo_thrd;
u8 res16[0x8];
- u32 dp_video_fifo_thrd;
- u8 res17[0x8];
- u32 dp_audio_margin;
- u32 dp_dn_spread_ctl_1;
- u32 dp_dn_spread_ctl_2;
- u8 res18[0x18];
- u32 dp_m_cal_ctl;
+ u32 audio_margin;
+
+ u32 dn_spread_ctl1;
+ u32 dn_spread_ctl2;
+ u8 res17[0x18];
+ u32 m_cal_ctl;
u32 m_vid_gen_filter_th;
- u8 res19[0x14];
+ u8 res18[0x10];
u32 m_aud_gen_filter_th;
+ u8 res50[0x4];
+
u32 aux_ch_sta;
u32 aux_err_num;
- u32 aux_ch_defer_dtl;
+ u32 aux_ch_defer_ctl;
u32 aux_rx_comm;
- u32 buf_data_ctl;
- u32 aux_ch_ctl_1;
+ u32 buffer_data_ctl;
+
+ u32 aux_ch_ctl1;
u32 aux_addr_7_0;
u32 aux_addr_15_8;
u32 aux_addr_19_16;
- u32 aux_ch_ctl_2;
- u8 res20[0x18];
- u32 buf_data_0;
- u8 res21[0x3c];
+ u32 aux_ch_ctl2;
+ u8 res19[0x18];
+ u32 buf_data0;
+ u8 res20[0x3c];
+
u32 soc_general_ctl;
+ u8 res21[0x8c];
+ u32 crc_con;
+ u32 crc_result;
+ u8 res22[0x8];
+
+ u32 common_int_mask1;
+ u32 common_int_mask2;
+ u32 common_int_mask3;
+ u32 common_int_mask4;
+ u32 int_sta_mask1;
+ u32 int_sta_mask2;
+ u32 int_sta_mask3;
+ u32 int_sta_mask4;
+ u32 int_sta_mask;
+ u32 crc_result2;
+ u32 scrambler_reset_cnt;
+
+ u32 pn_inv;
+ u32 psr_config;
+ u32 psr_command0;
+ u32 psr_command1;
+ u32 psr_crc_mon0;
+ u32 psr_crc_mon1;
+
+ u8 res24[0x30];
+ u32 phy_bist_ctrl;
+ u8 res25[0xc];
+ u32 phy_ctrl;
+ u8 res26[0x1c];
+ u32 test_pattern_gen_en;
+ u32 test_pattern_gen_ctrl;
};
-/* DP_TX_SW_RESET */
-#define RESET_DP_TX (1 << 0)
-
-/* DP_FUNC_EN_1 */
-#define MASTER_VID_FUNC_EN_N (1 << 7)
-#define SLAVE_VID_FUNC_EN_N (1 << 5)
-#define AUD_FIFO_FUNC_EN_N (1 << 4)
-#define AUD_FUNC_EN_N (1 << 3)
-#define HDCP_FUNC_EN_N (1 << 2)
-#define CRC_FUNC_EN_N (1 << 1)
-#define SW_FUNC_EN_N (1 << 0)
-
-/* DP_FUNC_EN_2 */
-#define SSC_FUNC_EN_N (1 << 7)
-#define AUX_FUNC_EN_N (1 << 2)
-#define SERDES_FIFO_FUNC_EN_N (1 << 1)
-#define LS_CLK_DOMAIN_FUNC_EN_N (1 << 0)
-
-/* DP_VIDEO_CTL_1 */
-#define VIDEO_EN (1 << 7)
-#define HDCP_VIDEO_MUTE (1 << 6)
-
-/* DP_VIDEO_CTL_1 */
-#define IN_D_RANGE_MASK (1 << 7)
+
+/* For DP VIDEO CTL 1 */
+#define VIDEO_EN_MASK (0x01 << 7)
+#define VIDEO_MUTE_MASK (0x01 << 6)
+
+/* For DP VIDEO CTL 4 */
+#define VIDEO_BIST_MASK (0x1 << 3)
+
+/* EXYNOS_DP_ANALOG_CTL_1 */
+#define SEL_BG_NEW_BANDGAP (0x0 << 6)
+#define SEL_BG_INTERNAL_RESISTOR (0x1 << 6)
+#define TX_TERMINAL_CTRL_73_OHM (0x0 << 4)
+#define TX_TERMINAL_CTRL_61_OHM (0x1 << 4)
+#define TX_TERMINAL_CTRL_50_OHM (0x2 << 4)
+#define TX_TERMINAL_CTRL_45_OHM (0x3 << 4)
+#define SWING_A_30PER_G_INCREASE (0x1 << 3)
+#define SWING_A_30PER_G_NORMAL (0x0 << 3)
+
+/* EXYNOS_DP_ANALOG_CTL_2 */
+#define CPREG_BLEED (0x1 << 4)
+#define SEL_24M (0x1 << 3)
+#define TX_DVDD_BIT_1_0000V (0x3 << 0)
+#define TX_DVDD_BIT_1_0625V (0x4 << 0)
+#define TX_DVDD_BIT_1_1250V (0x5 << 0)
+
+/* EXYNOS_DP_ANALOG_CTL_3 */
+#define DRIVE_DVDD_BIT_1_0000V (0x3 << 5)
+#define DRIVE_DVDD_BIT_1_0625V (0x4 << 5)
+#define DRIVE_DVDD_BIT_1_1250V (0x5 << 5)
+#define SEL_CURRENT_DEFAULT (0x0 << 3)
+#define VCO_BIT_000_MICRO (0x0 << 0)
+#define VCO_BIT_200_MICRO (0x1 << 0)
+#define VCO_BIT_300_MICRO (0x2 << 0)
+#define VCO_BIT_400_MICRO (0x3 << 0)
+#define VCO_BIT_500_MICRO (0x4 << 0)
+#define VCO_BIT_600_MICRO (0x5 << 0)
+#define VCO_BIT_700_MICRO (0x6 << 0)
+#define VCO_BIT_900_MICRO (0x7 << 0)
+
+/* EXYNOS_DP_PLL_FILTER_CTL_1 */
+#define PD_RING_OSC (0x1 << 6)
+#define AUX_TERMINAL_CTRL_52_OHM (0x3 << 4)
+#define AUX_TERMINAL_CTRL_69_OHM (0x2 << 4)
+#define AUX_TERMINAL_CTRL_102_OHM (0x1 << 4)
+#define AUX_TERMINAL_CTRL_200_OHM (0x0 << 4)
+#define TX_CUR1_1X (0x0 << 2)
+#define TX_CUR1_2X (0x1 << 2)
+#define TX_CUR1_3X (0x2 << 2)
+#define TX_CUR_1_MA (0x0 << 0)
+#define TX_CUR_2_MA (0x1 << 0)
+#define TX_CUR_3_MA (0x2 << 0)
+#define TX_CUR_4_MA (0x3 << 0)
+
+/* EXYNOS_DP_PLL_FILTER_CTL_2 */
+#define CH3_AMP_0_MV (0x3 << 12)
+#define CH2_AMP_0_MV (0x3 << 8)
+#define CH1_AMP_0_MV (0x3 << 4)
+#define CH0_AMP_0_MV (0x3 << 0)
+
+/* EXYNOS_DP_PLL_CTL */
+#define DP_PLL_PD (0x1 << 7)
+#define DP_PLL_RESET (0x1 << 6)
+#define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4)
+#define DP_PLL_REF_BIT_1_1250V (0x5 << 0)
+#define DP_PLL_REF_BIT_1_2500V (0x7 << 0)
+
+/* EXYNOS_DP_INT_CTL */
+#define SOFT_INT_CTRL (0x1 << 2)
+#define INT_POL (0x1 << 0)
+
+/* DP TX SW RESET */
+#define RESET_DP_TX (0x01 << 0)
+
+/* DP FUNC_EN_1 */
+#define MASTER_VID_FUNC_EN_N (0x1 << 7)
+#define SLAVE_VID_FUNC_EN_N (0x1 << 5)
+#define AUD_FIFO_FUNC_EN_N (0x1 << 4)
+#define AUD_FUNC_EN_N (0x1 << 3)
+#define HDCP_FUNC_EN_N (0x1 << 2)
+#define CRC_FUNC_EN_N (0x1 << 1)
+#define SW_FUNC_EN_N (0x1 << 0)
+
+/* DP FUNC_EN_2 */
+#define SSC_FUNC_EN_N (0x1 << 7)
+#define AUX_FUNC_EN_N (0x1 << 2)
+#define SERDES_FIFO_FUNC_EN_N (0x1 << 1)
+#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0)
+
+/* EXYNOS_DP_PHY_PD */
+#define PHY_PD (0x1 << 5)
+#define AUX_PD (0x1 << 4)
+#define CH3_PD (0x1 << 3)
+#define CH2_PD (0x1 << 2)
+#define CH1_PD (0x1 << 1)
+#define CH0_PD (0x1 << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_1 */
+#define VSYNC_DET (0x1 << 7)
+#define PLL_LOCK_CHG (0x1 << 6)
+#define SPDIF_ERR (0x1 << 5)
+#define SPDIF_UNSTBL (0x1 << 4)
+#define VID_FORMAT_CHG (0x1 << 3)
+#define AUD_CLK_CHG (0x1 << 2)
+#define VID_CLK_CHG (0x1 << 1)
+#define SW_INT (0x1 << 0)
+
+/* EXYNOS_DP_DEBUG_CTL */
+#define PLL_LOCK (0x1 << 4)
+#define F_PLL_LOCK (0x1 << 3)
+#define PLL_LOCK_CTRL (0x1 << 2)
+
+/* EXYNOS_DP_FUNC_EN_2 */
+#define SSC_FUNC_EN_N (0x1 << 7)
+#define AUX_FUNC_EN_N (0x1 << 2)
+#define SERDES_FIFO_FUNC_EN_N (0x1 << 1)
+#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_4 */
+#define PSR_ACTIVE (0x1 << 7)
+#define PSR_INACTIVE (0x1 << 6)
+#define SPDIF_BI_PHASE_ERR (0x1 << 5)
+#define HOTPLUG_CHG (0x1 << 2)
+#define HPD_LOST (0x1 << 1)
+#define PLUG (0x1 << 0)
+
+/* EXYNOS_DP_INT_STA */
+#define INT_HPD (0x1 << 6)
+#define HW_TRAINING_FINISH (0x1 << 5)
+#define RPLY_RECEIV (0x1 << 1)
+#define AUX_ERR (0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_3 */
+#define HPD_STATUS (0x1 << 6)
+#define F_HPD (0x1 << 5)
+#define HPD_CTRL (0x1 << 4)
+#define HDCP_RDY (0x1 << 3)
+#define STRM_VALID (0x1 << 2)
+#define F_VALID (0x1 << 1)
+#define VALID_CTRL (0x1 << 0)
+
+/* EXYNOS_DP_AUX_HW_RETRY_CTL */
+#define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8)
+#define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3)
+#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3)
+#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS (0x1 << 3)
+#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS (0x2 << 3)
+#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3)
+#define AUX_HW_RETRY_COUNT_SEL(x) (((x) & 0x7) << 0)
+
+/* EXYNOS_DP_AUX_CH_DEFER_CTL */
+#define DEFER_CTRL_EN (0x1 << 7)
+#define DEFER_COUNT(x) (((x) & 0x7f) << 0)
+
+#define COMMON_INT_MASK_1 (0)
+#define COMMON_INT_MASK_2 (0)
+#define COMMON_INT_MASK_3 (0)
+#define COMMON_INT_MASK_4 (0)
+#define INT_STA_MASK (0)
+
+/* EXYNOS_DP_BUFFER_DATA_CTL */
+#define BUF_CLR (0x1 << 7)
+#define BUF_DATA_COUNT(x) (((x) & 0x1f) << 0)
+
+/* EXYNOS_DP_AUX_ADDR_7_0 */
+#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff)
+
+/* EXYNOS_DP_AUX_ADDR_15_8 */
+#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff)
+
+/* EXYNOS_DP_AUX_ADDR_19_16 */
+#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f)
+
+/* EXYNOS_DP_AUX_CH_CTL_1 */
+#define AUX_LENGTH(x) (((x - 1) & 0xf) << 4)
+#define AUX_TX_COMM_MASK (0xf << 0)
+#define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3)
+#define AUX_TX_COMM_I2C_TRANSACTION (0x0 << 3)
+#define AUX_TX_COMM_MOT (0x1 << 2)
+#define AUX_TX_COMM_WRITE (0x0 << 0)
+#define AUX_TX_COMM_READ (0x1 << 0)
+
+/* EXYNOS_DP_AUX_CH_CTL_2 */
+#define ADDR_ONLY (0x1 << 1)
+#define AUX_EN (0x1 << 0)
+
+/* EXYNOS_DP_AUX_CH_STA */
+#define AUX_BUSY (0x1 << 4)
+#define AUX_STATUS_MASK (0xf << 0)
+
+/* EXYNOS_DP_AUX_RX_COMM */
+#define AUX_RX_COMM_I2C_DEFER (0x2 << 2)
+#define AUX_RX_COMM_AUX_DEFER (0x2 << 0)
+
+/* EXYNOS_DP_PHY_TEST */
+#define MACRO_RST (0x1 << 5)
+#define CH1_TEST (0x1 << 1)
+#define CH0_TEST (0x1 << 0)
+
+/* EXYNOS_DP_TRAINING_PTN_SET */
+#define SCRAMBLER_TYPE (0x1 << 9)
+#define HW_LINK_TRAINING_PATTERN (0x1 << 8)
+#define SCRAMBLING_DISABLE (0x1 << 5)
+#define SCRAMBLING_ENABLE (0x0 << 5)
+#define LINK_QUAL_PATTERN_SET_MASK (0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_PRBS7 (0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_D10_2 (0x1 << 2)
+#define LINK_QUAL_PATTERN_SET_DISABLE (0x0 << 2)
+#define SW_TRAINING_PATTERN_SET_MASK (0x3 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN2 (0x2 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0)
+#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0)
+
+/* EXYNOS_DP_TOTAL_LINE_CFG */
+#define TOTAL_LINE_CFG_L(x) ((x) & 0xff)
+#define TOTAL_LINE_CFG_H(x) ((((x) >> 8)) & 0xff)
+#define ACTIVE_LINE_CFG_L(x) ((x) & 0xff)
+#define ACTIVE_LINE_CFG_H(x) (((x) >> 8) & 0xff)
+#define TOTAL_PIXEL_CFG_L(x) ((x) & 0xff)
+#define TOTAL_PIXEL_CFG_H(x) ((((x) >> 8)) & 0xff)
+#define ACTIVE_PIXEL_CFG_L(x) ((x) & 0xff)
+#define ACTIVE_PIXEL_CFG_H(x) ((((x) >> 8)) & 0xff)
+
+#define H_F_PORCH_CFG_L(x) ((x) & 0xff)
+#define H_F_PORCH_CFG_H(x) ((((x) >> 8)) & 0xff)
+#define H_SYNC_PORCH_CFG_L(x) ((x) & 0xff)
+#define H_SYNC_PORCH_CFG_H(x) ((((x) >> 8)) & 0xff)
+#define H_B_PORCH_CFG_L(x) ((x) & 0xff)
+#define H_B_PORCH_CFG_H(x) ((((x) >> 8)) & 0xff)
+
+/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
+#define MAX_PRE_EMPHASIS_REACH_0 (0x1 << 5)
+#define PRE_EMPHASIS_SET_0_SET(x) (((x) & 0x3) << 3)
+#define PRE_EMPHASIS_SET_0_GET(x) (((x) >> 3) & 0x3)
+#define PRE_EMPHASIS_SET_0_MASK (0x3 << 3)
+#define PRE_EMPHASIS_SET_0_SHIFT (3)
+#define PRE_EMPHASIS_SET_0_LEVEL_3 (0x3 << 3)
+#define PRE_EMPHASIS_SET_0_LEVEL_2 (0x2 << 3)
+#define PRE_EMPHASIS_SET_0_LEVEL_1 (0x1 << 3)
+#define PRE_EMPHASIS_SET_0_LEVEL_0 (0x0 << 3)
+#define MAX_DRIVE_CURRENT_REACH_0 (0x1 << 2)
+#define DRIVE_CURRENT_SET_0_MASK (0x3 << 0)
+#define DRIVE_CURRENT_SET_0_SET(x) (((x) & 0x3) << 0)
+#define DRIVE_CURRENT_SET_0_GET(x) (((x) >> 0) & 0x3)
+#define DRIVE_CURRENT_SET_0_LEVEL_3 (0x3 << 0)
+#define DRIVE_CURRENT_SET_0_LEVEL_2 (0x2 << 0)
+#define DRIVE_CURRENT_SET_0_LEVEL_1 (0x1 << 0)
+#define DRIVE_CURRENT_SET_0_LEVEL_0 (0x0 << 0)
+
+/* EXYNOS_DP_LN1_LINK_TRAINING_CTL */
+#define MAX_PRE_EMPHASIS_REACH_1 (0x1 << 5)
+#define PRE_EMPHASIS_SET_1_SET(x) (((x) & 0x3) << 3)
+#define PRE_EMPHASIS_SET_1_GET(x) (((x) >> 3) & 0x3)
+#define PRE_EMPHASIS_SET_1_MASK (0x3 << 3)
+#define PRE_EMPHASIS_SET_1_SHIFT (3)
+#define PRE_EMPHASIS_SET_1_LEVEL_3 (0x3 << 3)
+#define PRE_EMPHASIS_SET_1_LEVEL_2 (0x2 << 3)
+#define PRE_EMPHASIS_SET_1_LEVEL_1 (0x1 << 3)
+#define PRE_EMPHASIS_SET_1_LEVEL_0 (0x0 << 3)
+#define MAX_DRIVE_CURRENT_REACH_1 (0x1 << 2)
+#define DRIVE_CURRENT_SET_1_MASK (0x3 << 0)
+#define DRIVE_CURRENT_SET_1_SET(x) (((x) & 0x3) << 0)
+#define DRIVE_CURRENT_SET_1_GET(x) (((x) >> 0) & 0x3)
+#define DRIVE_CURRENT_SET_1_LEVEL_3 (0x3 << 0)
+#define DRIVE_CURRENT_SET_1_LEVEL_2 (0x2 << 0)
+#define DRIVE_CURRENT_SET_1_LEVEL_1 (0x1 << 0)
+#define DRIVE_CURRENT_SET_1_LEVEL_0 (0x0 << 0)
+
+/* EXYNOS_DP_LN2_LINK_TRAINING_CTL */
+#define MAX_PRE_EMPHASIS_REACH_2 (0x1 << 5)
+#define PRE_EMPHASIS_SET_2_SET(x) (((x) & 0x3) << 3)
+#define PRE_EMPHASIS_SET_2_GET(x) (((x) >> 3) & 0x3)
+#define PRE_EMPHASIS_SET_2_MASK (0x3 << 3)
+#define PRE_EMPHASIS_SET_2_SHIFT (3)
+#define PRE_EMPHASIS_SET_2_LEVEL_3 (0x3 << 3)
+#define PRE_EMPHASIS_SET_2_LEVEL_2 (0x2 << 3)
+#define PRE_EMPHASIS_SET_2_LEVEL_1 (0x1 << 3)
+#define PRE_EMPHASIS_SET_2_LEVEL_0 (0x0 << 3)
+#define MAX_DRIVE_CURRENT_REACH_2 (0x1 << 2)
+#define DRIVE_CURRENT_SET_2_MASK (0x3 << 0)
+#define DRIVE_CURRENT_SET_2_SET(x) (((x) & 0x3) << 0)
+#define DRIVE_CURRENT_SET_2_GET(x) (((x) >> 0) & 0x3)
+#define DRIVE_CURRENT_SET_2_LEVEL_3 (0x3 << 0)
+#define DRIVE_CURRENT_SET_2_LEVEL_2 (0x2 << 0)
+#define DRIVE_CURRENT_SET_2_LEVEL_1 (0x1 << 0)
+#define DRIVE_CURRENT_SET_2_LEVEL_0 (0x0 << 0)
+
+/* EXYNOS_DP_LN3_LINK_TRAINING_CTL */
+#define MAX_PRE_EMPHASIS_REACH_3 (0x1 << 5)
+#define PRE_EMPHASIS_SET_3_SET(x) (((x) & 0x3) << 3)
+#define PRE_EMPHASIS_SET_3_GET(x) (((x) >> 3) & 0x3)
+#define PRE_EMPHASIS_SET_3_MASK (0x3 << 3)
+#define PRE_EMPHASIS_SET_3_SHIFT (3)
+#define PRE_EMPHASIS_SET_3_LEVEL_3 (0x3 << 3)
+#define PRE_EMPHASIS_SET_3_LEVEL_2 (0x2 << 3)
+#define PRE_EMPHASIS_SET_3_LEVEL_1 (0x1 << 3)
+#define PRE_EMPHASIS_SET_3_LEVEL_0 (0x0 << 3)
+#define MAX_DRIVE_CURRENT_REACH_3 (0x1 << 2)
+#define DRIVE_CURRENT_SET_3_MASK (0x3 << 0)
+#define DRIVE_CURRENT_SET_3_SET(x) (((x) & 0x3) << 0)
+#define DRIVE_CURRENT_SET_3_GET(x) (((x) >> 0) & 0x3)
+#define DRIVE_CURRENT_SET_3_LEVEL_3 (0x3 << 0)
+#define DRIVE_CURRENT_SET_3_LEVEL_2 (0x2 << 0)
+#define DRIVE_CURRENT_SET_3_LEVEL_1 (0x1 << 0)
+#define DRIVE_CURRENT_SET_3_LEVEL_0 (0x0 << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_10 */
+#define FORMAT_SEL (0x1 << 4)
+#define INTERACE_SCAN_CFG (0x1 << 2)
+#define INTERACE_SCAN_CFG_SHIFT (2)
+#define VSYNC_POLARITY_CFG (0x1 << 1)
+#define V_S_POLARITY_CFG_SHIFT (1)
+#define HSYNC_POLARITY_CFG (0x1 << 0)
+#define H_S_POLARITY_CFG_SHIFT (0)
+
+/* EXYNOS_DP_SOC_GENERAL_CTL */
+#define AUDIO_MODE_SPDIF_MODE (0x1 << 8)
+#define AUDIO_MODE_MASTER_MODE (0x0 << 8)
+#define MASTER_VIDEO_INTERLACE_EN (0x1 << 4)
+#define VIDEO_MASTER_CLK_SEL (0x1 << 2)
+#define VIDEO_MASTER_MODE_EN (0x1 << 1)
+#define VIDEO_MODE_MASK (0x1 << 0)
+#define VIDEO_MODE_SLAVE_MODE (0x1 << 0)
+#define VIDEO_MODE_MASTER_MODE (0x0 << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_1 */
+#define VIDEO_EN (0x1 << 7)
+#define HDCP_VIDEO_MUTE (0x1 << 6)
+
+/* EXYNOS_DP_VIDEO_CTL_2 */
+#define IN_D_RANGE_MASK (0x1 << 7)
#define IN_D_RANGE_SHIFT (7)
-#define IN_D_RANGE_CEA (1 << 7)
-#define IN_D_RANGE_VESA (0 << 7)
-#define IN_BPC_MASK (7 << 4)
+#define IN_D_RANGE_CEA (0x1 << 7)
+#define IN_D_RANGE_VESA (0x0 << 7)
+#define IN_BPC_MASK (0x7 << 4)
#define IN_BPC_SHIFT (4)
-#define IN_BPC_12_BITS (3 << 4)
-#define IN_BPC_10_BITS (2 << 4)
-#define IN_BPC_8_BITS (1 << 4)
-#define IN_BPC_6_BITS (0 << 4)
-#define IN_COLOR_F_MASK (3 << 0)
+#define IN_BPC_12_BITS (0x3 << 4)
+#define IN_BPC_10_BITS (0x2 << 4)
+#define IN_BPC_8_BITS (0x1 << 4)
+#define IN_BPC_6_BITS (0x0 << 4)
+#define IN_COLOR_F_MASK (0x3 << 0)
#define IN_COLOR_F_SHIFT (0)
-#define IN_COLOR_F_YCBCR444 (2 << 0)
-#define IN_COLOR_F_YCBCR422 (1 << 0)
-#define IN_COLOR_F_RGB (0 << 0)
+#define IN_COLOR_F_YCBCR444 (0x2 << 0)
+#define IN_COLOR_F_YCBCR422 (0x1 << 0)
+#define IN_COLOR_F_RGB (0x0 << 0)
-/* DP_VIDEO_CTL_3 */
-#define IN_YC_COEFFI_MASK (1 << 7)
+/* EXYNOS_DP_VIDEO_CTL_3 */
+#define IN_YC_COEFFI_MASK (0x1 << 7)
#define IN_YC_COEFFI_SHIFT (7)
-#define IN_YC_COEFFI_ITU709 (1 << 7)
-#define IN_YC_COEFFI_ITU601 (0 << 7)
-#define VID_CHK_UPDATE_TYPE_MASK (1 << 4)
+#define IN_YC_COEFFI_ITU709 (0x1 << 7)
+#define IN_YC_COEFFI_ITU601 (0x0 << 7)
+#define VID_CHK_UPDATE_TYPE_MASK (0x1 << 4)
#define VID_CHK_UPDATE_TYPE_SHIFT (4)
-#define VID_CHK_UPDATE_TYPE_1 (1 << 4)
-#define VID_CHK_UPDATE_TYPE_0 (0 << 4)
-
-/* DP_VIDEO_CTL_10 */
-#define FORMAT_SEL (1 << 4)
-#define INTERACE_SCAN_CFG (1 << 2)
-#define VSYNC_POLARITY_CFG (1 << 1)
-#define HSYNC_POLARITY_CFG (1 << 0)
-
-/* DP_LANE_MAP */
-#define LANE3_MAP_LOGIC_LANE_0 (0 << 6)
-#define LANE3_MAP_LOGIC_LANE_1 (1 << 6)
-#define LANE3_MAP_LOGIC_LANE_2 (2 << 6)
-#define LANE3_MAP_LOGIC_LANE_3 (3 << 6)
-#define LANE2_MAP_LOGIC_LANE_0 (0 << 4)
-#define LANE2_MAP_LOGIC_LANE_1 (1 << 4)
-#define LANE2_MAP_LOGIC_LANE_2 (2 << 4)
-#define LANE2_MAP_LOGIC_LANE_3 (3 << 4)
-#define LANE1_MAP_LOGIC_LANE_0 (0 << 2)
-#define LANE1_MAP_LOGIC_LANE_1 (1 << 2)
-#define LANE1_MAP_LOGIC_LANE_2 (2 << 2)
-#define LANE1_MAP_LOGIC_LANE_3 (3 << 2)
-#define LANE0_MAP_LOGIC_LANE_0 (0 << 0)
-#define LANE0_MAP_LOGIC_LANE_1 (1 << 0)
-#define LANE0_MAP_LOGIC_LANE_2 (2 << 0)
-#define LANE0_MAP_LOGIC_LANE_3 (3 << 0)
-
-/* DP_AUX_HW_RETRY_CTL */
-#define AUX_BIT_PERIOD_SHIFT 8
-#define AUX_BIT_PERIOD_MASK 7
-
-#define AUX_HW_RETRY_INTERVAL_SHIFT 3
-#define AUX_HW_RETRY_INTERVAL_600_US 0
-#define AUX_HW_RETRY_INTERVAL_800_US 1
-#define AUX_HW_RETRY_INTERVAL_1000_US 2
-#define AUX_HW_RETRY_INTERVAL_1800_US 3
-#define AUX_HW_RETRY_COUNT_SHIFT 0
-#define AUX_HW_RETRY_COUNT_MASK 7
-
-/* DP_COMMON_INT_STA_1 */
-#define VSYNC_DET (1 << 7)
-#define PLL_LOCK_CHG (1 << 6)
-#define SPDIF_ERR (1 << 5)
-#define SPDIF_UNSTBL (1 << 4)
-#define VID_FORMAT_CHG (1 << 3)
-#define AUD_CLK_CHG (1 << 2)
-#define VID_CLK_CHG (1 << 1)
-#define SW_INT (1 << 0)
-
-/* DP_COMMON_INT_STA_2 */
-#define ENC_EN_CHG (1 << 6)
-#define HW_BKSV_RDY (1 << 3)
-#define HW_SHA_DONE (1 << 2)
-#define HW_AUTH_STATE_CHG (1 << 1)
-#define HW_AUTH_DONE (1 << 0)
-
-/* DP_COMMON_INT_STA_3 */
-#define AFIFO_UNDER (1 << 7)
-#define AFIFO_OVER (1 << 6)
-#define R0_CHK_FLAG (1 << 5)
-
-/* DP_COMMON_INT_STA_4 */
-#define PSR_ACTIVE (1 << 7)
-#define PSR_INACTIVE (1 << 6)
-#define SPDIF_BI_PHASE_ERR (1 << 5)
-#define HOTPLUG_CHG (1 << 2)
-#define HPD_LOST (1 << 1)
-#define PLUG (1 << 0)
-
-/* DP_INT_STA */
-#define INT_HPD (1 << 6)
-#define HW_TRAINING_FINISH (1 << 5)
-#define RPLY_RECEIV (1 << 1)
-#define AUX_ERR (1 << 0)
-
-/* DP_INT_CTL */
-#define INT_POL0 (1 << 0)
-#define INT_POL1 (1 << 1)
-#define SOFT_INT_CTRL (1 << 2)
-
-/* DP_SYS_CTL_1 */
-#define DET_STA (1 << 2)
-#define FORCE_DET (1 << 1)
-#define DET_CTRL (1 << 0)
-
-/* DP_SYS_CTL_2 */
-#define CHA_CRI_SHIFT 4
-#define CHA_CRI_MASK 0xf
-#define CHA_STA (1 << 2)
-#define FORCE_CHA (1 << 1)
-#define CHA_CTRL (1 << 0)
-
-/* DP_SYS_CTL_3 */
-#define HPD_STATUS (1 << 6)
-#define F_HPD (1 << 5)
-#define HPD_CTRL (1 << 4)
-#define HDCP_RDY (1 << 3)
-#define STRM_VALID (1 << 2)
-#define F_VALID (1 << 1)
-#define VALID_CTRL (1 << 0)
-
-/* DP_SYS_CTL_4 */
-#define FIX_M_AUD (1 << 4)
-#define ENHANCED (1 << 3)
-#define FIX_M_VID (1 << 2)
-#define M_VID_UPDATE_CTRL (3 << 0)
-
-/* DP_TRAINING_PTN_SET */
-#define SCRAMBLER_TYPE (1 << 9)
-#define HW_LINK_TRAINING_PATTERN (1 << 8)
-#define SCRAMBLING_DISABLE (1 << 5)
-#define SCRAMBLING_ENABLE (0 << 5)
-#define LINK_QUAL_PATTERN_SET_MASK (3 << 2)
-#define LINK_QUAL_PATTERN_SET_PRBS7 (3 << 2)
-#define LINK_QUAL_PATTERN_SET_D10_2 (1 << 2)
-#define LINK_QUAL_PATTERN_SET_DISABLE (0 << 2)
-#define SW_TRAINING_PATTERN_SET_MASK (3 << 0)
-#define SW_TRAINING_PATTERN_SET_PTN2 (2 << 0)
-#define SW_TRAINING_PATTERN_SET_PTN1 (1 << 0)
-#define SW_TRAINING_PATTERN_SET_NORMAL (0 << 0)
-
-/* DP_LN0_LINK_TRAINING_CTL */
-#define PRE_EMPHASIS_SET_SHIFT (3)
-
-/* DP_DEBUG_CTL */
-#define PLL_LOCK (1 << 4)
-#define F_PLL_LOCK (1 << 3)
-#define PLL_LOCK_CTRL (1 << 2)
-#define PN_INV (1 << 0)
-
-/* DP_M_VID */
-#define M_VID_0_VALUE_SHIFT 0
-#define M_VID_1_VALUE_SHIFT 8
-#define M_VID_2_VALUE_SHIFT 16
-
-/* DP_M_VID */
-#define N_VID_0_VALUE_SHIFT 0
-#define N_VID_1_VALUE_SHIFT 8
-#define N_VID_2_VALUE_SHIFT 16
-
-/* DP_PLL_CTL */
-#define DP_PLL_PD (1 << 7)
-#define DP_PLL_RESET (1 << 6)
-#define DP_PLL_LOOP_BIT_DEFAULT (1 << 4)
-#define DP_PLL_REF_BIT_1_1250V (5 << 0)
-#define DP_PLL_REF_BIT_1_2500V (7 << 0)
-
-/* DP_PHY_PD */
-#define DP_PHY_PD (1 << 5)
-#define AUX_PD (1 << 4)
-#define CH3_PD (1 << 3)
-#define CH2_PD (1 << 2)
-#define CH1_PD (1 << 1)
-#define CH0_PD (1 << 0)
-
-/* DP_PHY_TEST */
-#define MACRO_RST (1 << 5)
-#define CH1_TEST (1 << 1)
-#define CH0_TEST (1 << 0)
-
-/* DP_AUX_CH_STA */
-#define AUX_BUSY (1 << 4)
-#define AUX_STATUS_MASK (0xf << 0)
+#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4)
-/* DP_AUX_CH_DEFER_CTL */
-#define DEFER_CTRL_EN (1 << 7)
-#define DEFER_COUNT_SHIFT 0
-#define DEFER_COUNT_MASK 0x7f
+/* EXYNOS_DP_TEST_PATTERN_GEN_EN */
+#define TEST_PATTERN_GEN_EN (0x1 << 0)
+#define TEST_PATTERN_GEN_DIS (0x0 << 0)
-/* DP_AUX_RX_COMM */
-#define AUX_RX_COMM_I2C_DEFER (2 << 2)
-#define AUX_RX_COMM_AUX_DEFER (2 << 0)
+/* EXYNOS_DP_TEST_PATTERN_GEN_CTRL */
+#define TEST_PATTERN_MODE_COLOR_SQUARE (0x3 << 0)
+#define TEST_PATTERN_MODE_BALCK_WHITE_V_LINES (0x2 << 0)
+#define TEST_PATTERN_MODE_COLOR_RAMP (0x1 << 0)
-/* DP_BUFFER_DATA_CTL */
-#define BUF_CLR (1 << 7)
+/* EXYNOS_DP_VIDEO_CTL_4 */
+#define BIST_EN (0x1 << 3)
+#define BIST_WIDTH_MASK (0x1 << 2)
+#define BIST_WIDTH_BAR_32_PIXEL (0x0 << 2)
+#define BIST_WIDTH_BAR_64_PIXEL (0x1 << 2)
+#define BIST_TYPE_MASK (0x3 << 0)
+#define BIST_TYPE_COLOR_BAR (0x0 << 0)
+#define BIST_TYPE_WHITE_GRAY_BLACK_BAR (0x1 << 0)
+#define BIST_TYPE_MOBILE_WHITE_BAR (0x2 << 0)
-/* Maximum number of tries for Aux Transaction */
-#define MAX_AUX_RETRY_COUNT 10
+/* EXYNOS_DP_SYS_CTL_1 */
+#define DET_STA (0x1 << 2)
+#define FORCE_DET (0x1 << 1)
+#define DET_CTRL (0x1 << 0)
-/* DP_AUX_CH_CTL_1 */
-#define AUX_LENGTH_SHIFT 4
-#define AUX_LENGTH_MASK 0xf
+/* EXYNOS_DP_SYS_CTL_2 */
+#define CHA_CRI(x) (((x) & 0xf) << 4)
+#define CHA_STA (0x1 << 2)
+#define FORCE_CHA (0x1 << 1)
+#define CHA_CTRL (0x1 << 0)
-#define AUX_TX_COMM_MASK (0xf << 0)
-#define AUX_TX_COMM_DP_TRANSACTION (1 << 3)
-#define AUX_TX_COMM_I2C_TRANSACTION (0 << 3)
-#define AUX_TX_COMM_MOT (1 << 2)
-#define AUX_TX_COMM_WRITE (0 << 0)
-#define AUX_TX_COMM_READ (1 << 0)
-
-/* DP_AUX_ADDR_7_0 */
-#define AUX_ADDR_7_0_SHIFT 0
-#define AUX_ADDR_7_0_MASK 0xff
-
-/* DP_AUX_ADDR_15_8 */
-#define AUX_ADDR_15_8_SHIFT 8
-#define AUX_ADDR_15_8_MASK 0xff
-
-/* DP_AUX_ADDR_19_16 */
-#define AUX_ADDR_19_16_SHIFT 16
-#define AUX_ADDR_19_16_MASK 0x0f
-
-/* DP_AUX_CH_CTL_2 */
-#define ADDR_ONLY (1 << 1)
-#define AUX_EN (1 << 0)
-
-/* DP_SOC_GENERAL_CTL */
-#define AUDIO_MODE_SPDIF_MODE (1 << 8)
-#define AUDIO_MODE_MASTER_MODE (0 << 8)
-#define MASTER_VIDEO_INTERLACE_EN (1 << 4)
-#define VIDEO_MASTER_CLK_SEL (1 << 2)
-#define VIDEO_MASTER_MODE_EN (1 << 1)
-#define VIDEO_MODE_MASK (1 << 0)
-#define VIDEO_MODE_SLAVE_MODE (1 << 0)
-#define VIDEO_MODE_MASTER_MODE (0 << 0)
-
-#define HW_TRAINING_ERROR_CODE (7<<4)
-#define HW_TRAINING_EN (1<<0)
+/* EXYNOS_DP_SYS_CTL_3 */
+#define HPD_STATUS (0x1 << 6)
+#define F_HPD (0x1 << 5)
+#define HPD_CTRL (0x1 << 4)
+#define HDCP_RDY (0x1 << 3)
+#define STRM_VALID (0x1 << 2)
+#define F_VALID (0x1 << 1)
+#define VALID_CTRL (0x1 << 0)
-/* I2C EDID Chip ID, Slave Address */
-#define I2C_EDID_DEVICE_ADDR 0x50
-#define I2C_E_EDID_DEVICE_ADDR 0x30
+/* EXYNOS_DP_SYS_CTL_4 */
+#define FIX_M_AUD (0x1 << 4)
+#define ENHANCED (0x1 << 3)
+#define FIX_M_VID (0x1 << 2)
+#define M_VID_UPDATE_CTRL (0x3 << 0)
+
+/* EXYNOS_M_VID_X */
+#define M_VID0_CFG(x) ((x) & 0xff)
+#define M_VID1_CFG(x) (((x) >> 8) & 0xff)
+#define M_VID2_CFG(x) (((x) >> 16) & 0xff)
-#define EDID_BLOCK_LENGTH 0x80
-#define EDID_HEADER_PATTERN 0x00
-#define EDID_EXTENSION_FLAG 0x7e
-#define EDID_CHECKSUM 0x7f
+/* EXYNOS_M_VID_X */
+#define N_VID0_CFG(x) ((x) & 0xff)
+#define N_VID1_CFG(x) (((x) >> 8) & 0xff)
+#define N_VID2_CFG(x) (((x) >> 16) & 0xff)
+
+/* DPCD_TRAINING_PATTERN_SET */
+#define DPCD_SCRAMBLING_DISABLED (0x1 << 5)
+#define DPCD_SCRAMBLING_ENABLED (0x0 << 5)
+#define DPCD_TRAINING_PATTERN_2 (0x2 << 0)
+#define DPCD_TRAINING_PATTERN_1 (0x1 << 0)
+#define DPCD_TRAINING_PATTERN_DISABLED (0x0 << 0)
/* Definition for DPCD Register */
-#define DPCD_ADDR_DPCD_REV 0x0000
-#define DPCD_ADDR_MAX_LINK_RATE 0x0001
-#define DPCD_ADDR_MAX_LANE_COUNT 0x0002
-#define DPCD_ADDR_LINK_BW_SET 0x0100
-#define DPCD_ADDR_LANE_COUNT_SET 0x0101
-#define DPCD_ADDR_TRAINING_PATTERN_SET 0x0102
-#define DPCD_ADDR_TRAINING_LANE0_SET 0x0103
-#define DPCD_ADDR_LANE0_1_STATUS 0x0202
-#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED 0x0204
-#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x0206
-#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x0207
-#define DPCD_ADDR_TEST_REQUEST 0x0218
-#define DPCD_ADDR_TEST_RESPONSE 0x0260
-#define DPCD_ADDR_TEST_EDID_CHECKSUM 0x0261
-#define DPCD_ADDR_SINK_POWER_STATE 0x0600
-
-/* DPCD_ADDR_MAX_LANE_COUNT */
-#define DPCD_MAX_LANE_COUNT_MASK 0x1f
-
-/* DPCD_ADDR_LANE_COUNT_SET */
-#define DPCD_ENHANCED_FRAME_EN (1 << 7)
-#define DPCD_LANE_COUNT_SET_MASK 0x1f
-
-/* DPCD_ADDR_TRAINING_PATTERN_SET */
-#define DPCD_SCRAMBLING_DISABLED (1 << 5)
-#define DPCD_SCRAMBLING_ENABLED (0 << 5)
-#define DPCD_TRAINING_PATTERN_2 (2 << 0)
-#define DPCD_TRAINING_PATTERN_1 (1 << 0)
-#define DPCD_TRAINING_PATTERN_DISABLED (0 << 0)
-
-/* DPCD_ADDR_LANE0_1_STATUS */
-#define DPCD_LANE_SYMBOL_LOCKED (1 << 2)
-#define DPCD_LANE_CHANNEL_EQ_DONE (1 << 1)
-#define DPCD_LANE_CR_DONE (1 << 0)
-#define DPCD_CHANNEL_EQ_BITS (DPCD_LANE_CR_DONE | \
- DPCD_LANE_CHANNEL_EQ_DONE | \
- DPCD_LANE_SYMBOL_LOCKED)
-
-/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
-#define DPCD_LINK_STATUS_UPDATED (1 << 7)
-#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6)
-#define DPCD_INTERLANE_ALIGN_DONE (1 << 0)
-
-/* DPCD_ADDR_TEST_REQUEST */
-#define DPCD_TEST_EDID_READ (1 << 2)
-
-/* DPCD_ADDR_TEST_RESPONSE */
-#define DPCD_TEST_EDID_CHECKSUM_WRITE (1 << 2)
-
-/* DPCD_ADDR_SINK_POWER_STATE */
-#define DPCD_SET_POWER_STATE_D0 (1 << 0)
-#define DPCD_SET_POWER_STATE_D4 (2 << 0)
-
-/* Allow DP Gating clock and set FIMD source to 267 Mhz for DP */
-void clock_init_dp_clock(void);
+#define DPCD_DPCD_REV (0x0000)
+#define DPCD_MAX_LINK_RATE (0x0001)
+#define DPCD_MAX_LANE_COUNT (0x0002)
+#define DPCD_LINK_BW_SET (0x0100)
+#define DPCD_LANE_COUNT_SET (0x0101)
+#define DPCD_TRAINING_PATTERN_SET (0x0102)
+#define DPCD_TRAINING_LANE0_SET (0x0103)
+#define DPCD_LANE0_1_STATUS (0x0202)
+#define DPCD_LN_ALIGN_UPDATED (0x0204)
+#define DPCD_ADJUST_REQUEST_LANE0_1 (0x0206)
+#define DPCD_ADJUST_REQUEST_LANE2_3 (0x0207)
+#define DPCD_TEST_REQUEST (0x0218)
+#define DPCD_TEST_RESPONSE (0x0260)
+#define DPCD_TEST_EDID_CHECKSUM (0x0261)
+#define DPCD_SINK_POWER_STATE (0x0600)
+
+/* DPCD_TEST_REQUEST */
+#define DPCD_TEST_EDID_READ (0x1 << 2)
+
+/* DPCD_TEST_RESPONSE */
+#define DPCD_TEST_EDID_CHECKSUM_WRITE (0x1 << 2)
+
+/* DPCD_SINK_POWER_STATE */
+#define DPCD_SET_POWER_STATE_D0 (0x1 << 0)
+#define DPCD_SET_POWER_STATE_D4 (0x2 << 0)
+
+/* I2C EDID Chip ID, Slave Address */
+#define I2C_EDID_DEVICE_ADDR (0x50)
+#define I2C_E_EDID_DEVICE_ADDR (0x30)
+#define EDID_BLOCK_LENGTH (0x80)
+#define EDID_HEADER_PATTERN (0x00)
+#define EDID_EXTENSION_FLAG (0x7e)
+#define EDID_CHECKSUM (0x7f)
+
+/* DPCD_LANE0_1_STATUS */
+#define DPCD_LANE1_SYMBOL_LOCKED (0x1 << 6)
+#define DPCD_LANE1_CHANNEL_EQ_DONE (0x1 << 5)
+#define DPCD_LANE1_CR_DONE (0x1 << 4)
+#define DPCD_LANE0_SYMBOL_LOCKED (0x1 << 2)
+#define DPCD_LANE0_CHANNEL_EQ_DONE (0x1 << 1)
+#define DPCD_LANE0_CR_DONE (0x1 << 0)
+
+/* DPCD_ADJUST_REQUEST_LANE0_1 */
+#define DPCD_PRE_EMPHASIS_LANE1_MASK (0x3 << 6)
+#define DPCD_PRE_EMPHASIS_LANE1(x) (((x) >> 6) & 0x3)
+#define DPCD_PRE_EMPHASIS_LANE1_LEVEL_3 (0x3 << 6)
+#define DPCD_PRE_EMPHASIS_LANE1_LEVEL_2 (0x2 << 6)
+#define DPCD_PRE_EMPHASIS_LANE1_LEVEL_1 (0x1 << 6)
+#define DPCD_PRE_EMPHASIS_LANE1_LEVEL_0 (0x0 << 6)
+#define DPCD_VOLTAGE_SWING_LANE1_MASK (0x3 << 4)
+#define DPCD_VOLTAGE_SWING_LANE1(x) (((x) >> 4) & 0x3)
+#define DPCD_VOLTAGE_SWING_LANE1_LEVEL_3 (0x3 << 4)
+#define DPCD_VOLTAGE_SWING_LANE1_LEVEL_2 (0x2 << 4)
+#define DPCD_VOLTAGE_SWING_LANE1_LEVEL_1 (0x1 << 4)
+#define DPCD_VOLTAGE_SWING_LANE1_LEVEL_0 (0x0 << 4)
+#define DPCD_PRE_EMPHASIS_LANE0_MASK (0x3 << 2)
+#define DPCD_PRE_EMPHASIS_LANE0(x) (((x) >> 2) & 0x3)
+#define DPCD_PRE_EMPHASIS_LANE0_LEVEL_3 (0x3 << 2)
+#define DPCD_PRE_EMPHASIS_LANE0_LEVEL_2 (0x2 << 2)
+#define DPCD_PRE_EMPHASIS_LANE0_LEVEL_1 (0x1 << 2)
+#define DPCD_PRE_EMPHASIS_LANE0_LEVEL_0 (0x0 << 2)
+#define DPCD_VOLTAGE_SWING_LANE0_MASK (0x3 << 0)
+#define DPCD_VOLTAGE_SWING_LANE0(x) (((x) >> 0) & 0x3)
+#define DPCD_VOLTAGE_SWING_LANE0_LEVEL_3 (0x3 << 0)
+#define DPCD_VOLTAGE_SWING_LANE0_LEVEL_2 (0x2 << 0)
+#define DPCD_VOLTAGE_SWING_LANE0_LEVEL_1 (0x1 << 0)
+#define DPCD_VOLTAGE_SWING_LANE0_LEVEL_0 (0x0 << 0)
+
+/* DPCD_ADJUST_REQUEST_LANE2_3 */
+#define DPCD_PRE_EMPHASIS_LANE2_MASK (0x3 << 6)
+#define DPCD_PRE_EMPHASIS_LANE2(x) (((x) >> 6) & 0x3)
+#define DPCD_PRE_EMPHASIS_LANE2_LEVEL_3 (0x3 << 6)
+#define DPCD_PRE_EMPHASIS_LANE2_LEVEL_2 (0x2 << 6)
+#define DPCD_PRE_EMPHASIS_LANE2_LEVEL_1 (0x1 << 6)
+#define DPCD_PRE_EMPHASIS_LANE2_LEVEL_0 (0x0 << 6)
+#define DPCD_VOLTAGE_SWING_LANE2_MASK (0x3 << 4)
+#define DPCD_VOLTAGE_SWING_LANE2(x) (((x) >> 4) & 0x3)
+#define DPCD_VOLTAGE_SWING_LANE2_LEVEL_3 (0x3 << 4)
+#define DPCD_VOLTAGE_SWING_LANE2_LEVEL_2 (0x2 << 4)
+#define DPCD_VOLTAGE_SWING_LANE2_LEVEL_1 (0x1 << 4)
+#define DPCD_VOLTAGE_SWING_LANE2_LEVEL_0 (0x0 << 4)
+#define DPCD_PRE_EMPHASIS_LANE3_MASK (0x3 << 2)
+#define DPCD_PRE_EMPHASIS_LANE3(x) (((x) >> 2) & 0x3)
+#define DPCD_PRE_EMPHASIS_LANE3_LEVEL_3 (0x3 << 2)
+#define DPCD_PRE_EMPHASIS_LANE3_LEVEL_2 (0x2 << 2)
+#define DPCD_PRE_EMPHASIS_LANE3_LEVEL_1 (0x1 << 2)
+#define DPCD_PRE_EMPHASIS_LANE3_LEVEL_0 (0x0 << 2)
+#define DPCD_VOLTAGE_SWING_LANE3_MASK (0x3 << 0)
+#define DPCD_VOLTAGE_SWING_LANE3(x) (((x) >> 0) & 0x3)
+#define DPCD_VOLTAGE_SWING_LANE3_LEVEL_3 (0x3 << 0)
+#define DPCD_VOLTAGE_SWING_LANE3_LEVEL_2 (0x2 << 0)
+#define DPCD_VOLTAGE_SWING_LANE3_LEVEL_1 (0x1 << 0)
+#define DPCD_VOLTAGE_SWING_LANE3_LEVEL_0 (0x0 << 0)
+
+/* DPCD_LANE_COUNT_SET */
+#define DPCD_ENHANCED_FRAME_EN (0x1 << 7)
+#define DPCD_LN_COUNT_SET(x) ((x) & 0x1f)
+
+/* DPCD_LANE_ALIGN__STATUS_UPDATED */
+#define DPCD_LINK_STATUS_UPDATED (0x1 << 7)
+#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED (0x1 << 6)
+#define DPCD_INTERLANE_ALIGN_DONE (0x1 << 0)
+
+/* DPCD_TRAINING_LANE0_SET */
+#define DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_3 (0x3 << 3)
+#define DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_2 (0x2 << 3)
+#define DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_1 (0x1 << 3)
+#define DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 (0x0 << 3)
+#define DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_3 (0x3 << 0)
+#define DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_2 (0x2 << 0)
+#define DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_1 (0x1 << 0)
+#define DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0 (0x0 << 0)
+
+#define DPCD_REQ_ADJ_SWING (0x00)
+#define DPCD_REQ_ADJ_EMPHASIS (0x01)
+
+#define DP_LANE_STAT_CR_DONE (0x01 << 0)
+#define DP_LANE_STAT_CE_DONE (0x01 << 1)
+#define DP_LANE_STAT_SYM_LOCK (0x01 << 2)
+
+struct exynos_fb {
+ u32 vidcon0;
+ u32 vidcon1;
+ u32 vidcon2;
+ u32 vidcon3;
+ u32 vidtcon0;
+ u32 vidtcon1;
+ u32 vidtcon2;
+ u32 vidtcon3;
+ u32 wincon0;
+ u32 wincon1;
+ u32 wincon2;
+ u32 wincon3;
+ u32 wincon4;
+
+ u32 winshmap;
+ u32 res1;
+
+ u32 winchmap2;
+ u32 vidosd0a;
+ u32 vidosd0b;
+ u32 vidosd0c;
+ u32 res2;
+
+ u32 vidosd1a;
+ u32 vidosd1b;
+ u32 vidosd1c;
+ u32 vidosd1d;
+
+ u32 vidosd2a;
+ u32 vidosd2b;
+ u32 vidosd2c;
+ u32 vidosd2d;
+
+ u32 vidosd3a;
+ u32 vidosd3b;
+ u32 vidosd3c;
+ u32 res3;
+
+ u32 vidosd4a;
+ u32 vidosd4b;
+ u32 vidosd4c;
+ u32 res4[5];
+
+ u32 vidw00add0b0;
+ u32 vidw00add0b1;
+ u32 vidw01add0b0;
+ u32 vidw01add0b1;
+
+ u32 vidw02add0b0;
+ u32 vidw02add0b1;
+ u32 vidw03add0b0;
+ u32 vidw03add0b1;
+ u32 vidw04add0b0;
+ u32 vidw04add0b1;
+ u32 res5[2];
+
+ u32 vidw00add1b0;
+ u32 vidw00add1b1;
+ u32 vidw01add1b0;
+ u32 vidw01add1b1;
+
+ u32 vidw02add1b0;
+ u32 vidw02add1b1;
+ u32 vidw03add1b0;
+ u32 vidw03add1b1;
+
+ u32 vidw04add1b0;
+ u32 vidw04add1b1;
+ u32 res7[2];
+
+ u32 vidw00add2;
+ u32 vidw01add2;
+ u32 vidw02add2;
+ u32 vidw03add2;
+ u32 vidw04add2;
+ u32 res8[7];
+
+ u32 vidintcon0;
+ u32 vidintcon1;
+ u32 res9[1];
+
+ u32 w1keycon0;
+ u32 w1keycon1;
+ u32 w2keycon0;
+ u32 w2keycon1;
+ u32 w3keycon0;
+ u32 w3keycon1;
+ u32 w4keycon0;
+ u32 w4keycon1;
+
+ u32 w1keyalpha;
+ u32 w2keyalpha;
+ u32 w3keyalpha;
+ u32 w4keyalpha;
+
+ u32 dithmode;
+ u32 res10[2];
+
+ u32 win0map;
+ u32 win1map;
+ u32 win2map;
+ u32 win3map;
+ u32 win4map;
+ u32 res11[1];
+
+ u32 wpalcon_h;
+ u32 wpalcon_l;
+
+ u32 trigcon;
+ u32 res12[2];
+
+ u32 i80ifcona0;
+ u32 i80ifcona1;
+ u32 i80ifconb0;
+ u32 i80ifconb1;
+
+ u32 colorgaincon;
+ u32 res13[2];
+
+ u32 ldi_cmdcon0;
+ u32 ldi_cmdcon1;
+ u32 res14[1];
+
+ /* To be updated */
+
+ u8 res15[156];
+ u32 dualrgb;
+ u8 res16[16];
+ u32 dp_mie_clkcon;
+};
+
+
+/* LCD IF register offset */
+#define EXYNOS5_LCD_IF_BASE_OFFSET 0x20000
+
+static inline u32 exynos_fimd_get_base_offset(void)
+{
+ return EXYNOS5_LCD_IF_BASE_OFFSET/4;
+}
+
+/*
+ * Register offsets
+*/
+#define EXYNOS_WINCON(x) (x)
+#define EXYNOS_VIDOSD(x) (x * 4)
+#define EXYNOS_BUFFER_OFFSET(x) (x * 2)
+#define EXYNOS_BUFFER_SIZE(x) (x)
+
+/*
+ * Bit Definitions
+*/
+
+/* VIDCON0 */
+#define EXYNOS_VIDCON0_DSI_DISABLE (0 << 30)
+#define EXYNOS_VIDCON0_DSI_ENABLE (1 << 30)
+#define EXYNOS_VIDCON0_SCAN_PROGRESSIVE (0 << 29)
+#define EXYNOS_VIDCON0_SCAN_INTERLACE (1 << 29)
+#define EXYNOS_VIDCON0_SCAN_MASK (1 << 29)
+#define EXYNOS_VIDCON0_VIDOUT_RGB (0 << 26)
+#define EXYNOS_VIDCON0_VIDOUT_ITU (1 << 26)
+#define EXYNOS_VIDCON0_VIDOUT_I80LDI0 (2 << 26)
+#define EXYNOS_VIDCON0_VIDOUT_I80LDI1 (3 << 26)
+#define EXYNOS_VIDCON0_VIDOUT_WB_RGB (4 << 26)
+#define EXYNOS_VIDCON0_VIDOUT_WB_I80LDI0 (6 << 26)
+#define EXYNOS_VIDCON0_VIDOUT_WB_I80LDI1 (7 << 26)
+#define EXYNOS_VIDCON0_VIDOUT_MASK (7 << 26)
+#define EXYNOS_VIDCON0_PNRMODE_RGB_P (0 << 17)
+#define EXYNOS_VIDCON0_PNRMODE_BGR_P (1 << 17)
+#define EXYNOS_VIDCON0_PNRMODE_RGB_S (2 << 17)
+#define EXYNOS_VIDCON0_PNRMODE_BGR_S (3 << 17)
+#define EXYNOS_VIDCON0_PNRMODE_MASK (3 << 17)
+#define EXYNOS_VIDCON0_PNRMODE_SHIFT (17)
+#define EXYNOS_VIDCON0_CLKVALUP_ALWAYS (0 << 16)
+#define EXYNOS_VIDCON0_CLKVALUP_START_FRAME (1 << 16)
+#define EXYNOS_VIDCON0_CLKVALUP_MASK (1 << 16)
+#define EXYNOS_VIDCON0_CLKVAL_F(x) (((x) & 0xff) << 6)
+#define EXYNOS_VIDCON0_VCLKEN_NORMAL (0 << 5)
+#define EXYNOS_VIDCON0_VCLKEN_FREERUN (1 << 5)
+#define EXYNOS_VIDCON0_VCLKEN_MASK (1 << 5)
+#define EXYNOS_VIDCON0_CLKDIR_DIRECTED (0 << 4)
+#define EXYNOS_VIDCON0_CLKDIR_DIVIDED (1 << 4)
+#define EXYNOS_VIDCON0_CLKDIR_MASK (1 << 4)
+#define EXYNOS_VIDCON0_CLKSEL_HCLK (0 << 2)
+#define EXYNOS_VIDCON0_CLKSEL_SCLK (1 << 2)
+#define EXYNOS_VIDCON0_CLKSEL_MASK (1 << 2)
+#define EXYNOS_VIDCON0_ENVID_ENABLE (1 << 1)
+#define EXYNOS_VIDCON0_ENVID_DISABLE (0 << 1)
+#define EXYNOS_VIDCON0_ENVID_F_ENABLE (1 << 0)
+#define EXYNOS_VIDCON0_ENVID_F_DISABLE (0 << 0)
+
+/* VIDCON1 */
+#define EXYNOS_VIDCON1_IVCLK_FALLING_EDGE (0 << 7)
+#define EXYNOS_VIDCON1_IVCLK_RISING_EDGE (1 << 7)
+#define EXYNOS_VIDCON1_IHSYNC_NORMAL (0 << 6)
+#define EXYNOS_VIDCON1_IHSYNC_INVERT (1 << 6)
+#define EXYNOS_VIDCON1_IVSYNC_NORMAL (0 << 5)
+#define EXYNOS_VIDCON1_IVSYNC_INVERT (1 << 5)
+#define EXYNOS_VIDCON1_IVDEN_NORMAL (0 << 4)
+#define EXYNOS_VIDCON1_IVDEN_INVERT (1 << 4)
+
+/* VIDCON2 */
+#define EXYNOS_VIDCON2_EN601_DISABLE (0 << 23)
+#define EXYNOS_VIDCON2_EN601_ENABLE (1 << 23)
+#define EXYNOS_VIDCON2_EN601_MASK (1 << 23)
+#define EXYNOS_VIDCON2_WB_DISABLE (0 << 15)
+#define EXYNOS_VIDCON2_WB_ENABLE (1 << 15)
+#define EXYNOS_VIDCON2_WB_MASK (1 << 15)
+#define EXYNOS_VIDCON2_TVFORMATSEL_HW (0 << 14)
+#define EXYNOS_VIDCON2_TVFORMATSEL_SW (1 << 14)
+#define EXYNOS_VIDCON2_TVFORMATSEL_MASK (1 << 14)
+#define EXYNOS_VIDCON2_TVFORMATSEL_YUV422 (1 << 12)
+#define EXYNOS_VIDCON2_TVFORMATSEL_YUV444 (2 << 12)
+#define EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK (3 << 12)
+#define EXYNOS_VIDCON2_ORGYUV_YCBCR (0 << 8)
+#define EXYNOS_VIDCON2_ORGYUV_CBCRY (1 << 8)
+#define EXYNOS_VIDCON2_ORGYUV_MASK (1 << 8)
+#define EXYNOS_VIDCON2_YUVORD_CBCR (0 << 7)
+#define EXYNOS_VIDCON2_YUVORD_CRCB (1 << 7)
+#define EXYNOS_VIDCON2_YUVORD_MASK (1 << 7)
+
+/* PRTCON */
+#define EXYNOS_PRTCON_UPDATABLE (0 << 11)
+#define EXYNOS_PRTCON_PROTECT (1 << 11)
+
+/* VIDTCON0 */
+#define EXYNOS_VIDTCON0_VBPDE(x) (((x) & 0xff) << 24)
+#define EXYNOS_VIDTCON0_VBPD(x) (((x) & 0xff) << 16)
+#define EXYNOS_VIDTCON0_VFPD(x) (((x) & 0xff) << 8)
+#define EXYNOS_VIDTCON0_VSPW(x) (((x) & 0xff) << 0)
+
+/* VIDTCON1 */
+#define EXYNOS_VIDTCON1_VFPDE(x) (((x) & 0xff) << 24)
+#define EXYNOS_VIDTCON1_HBPD(x) (((x) & 0xff) << 16)
+#define EXYNOS_VIDTCON1_HFPD(x) (((x) & 0xff) << 8)
+#define EXYNOS_VIDTCON1_HSPW(x) (((x) & 0xff) << 0)
+
+/* VIDTCON2 */
+#define EXYNOS_VIDTCON2_LINEVAL(x) (((x) & 0x7ff) << 11)
+#define EXYNOS_VIDTCON2_HOZVAL(x) (((x) & 0x7ff) << 0)
+#define EXYNOS_VIDTCON2_LINEVAL_E(x) ((((x) & 0x800) >> 11) << 23)
+#define EXYNOS_VIDTCON2_HOZVAL_E(x) ((((x) & 0x800) >> 11) << 22)
+
+/* Window 0~4 Control - WINCONx */
+#define EXYNOS_WINCON_DATAPATH_DMA (0 << 22)
+#define EXYNOS_WINCON_DATAPATH_LOCAL (1 << 22)
+#define EXYNOS_WINCON_DATAPATH_MASK (1 << 22)
+#define EXYNOS_WINCON_BUFSEL_0 (0 << 20)
+#define EXYNOS_WINCON_BUFSEL_1 (1 << 20)
+#define EXYNOS_WINCON_BUFSEL_MASK (1 << 20)
+#define EXYNOS_WINCON_BUFSEL_SHIFT (20)
+#define EXYNOS_WINCON_BUFAUTO_DISABLE (0 << 19)
+#define EXYNOS_WINCON_BUFAUTO_ENABLE (1 << 19)
+#define EXYNOS_WINCON_BUFAUTO_MASK (1 << 19)
+#define EXYNOS_WINCON_BITSWP_DISABLE (0 << 18)
+#define EXYNOS_WINCON_BITSWP_ENABLE (1 << 18)
+#define EXYNOS_WINCON_BITSWP_SHIFT (18)
+#define EXYNOS_WINCON_BYTESWP_DISABLE (0 << 17)
+#define EXYNOS_WINCON_BYTESWP_ENABLE (1 << 17)
+#define EXYNOS_WINCON_BYTESWP_SHIFT (17)
+#define EXYNOS_WINCON_HAWSWP_DISABLE (0 << 16)
+#define EXYNOS_WINCON_HAWSWP_ENABLE (1 << 16)
+#define EXYNOS_WINCON_HAWSWP_SHIFT (16)
+#define EXYNOS_WINCON_WSWP_DISABLE (0 << 15)
+#define EXYNOS_WINCON_WSWP_ENABLE (1 << 15)
+#define EXYNOS_WINCON_WSWP_SHIFT (15)
+#define EXYNOS_WINCON_INRGB_RGB (0 << 13)
+#define EXYNOS_WINCON_INRGB_YUV (1 << 13)
+#define EXYNOS_WINCON_INRGB_MASK (1 << 13)
+#define EXYNOS_WINCON_BURSTLEN_16WORD (0 << 9)
+#define EXYNOS_WINCON_BURSTLEN_8WORD (1 << 9)
+#define EXYNOS_WINCON_BURSTLEN_4WORD (2 << 9)
+#define EXYNOS_WINCON_BURSTLEN_MASK (3 << 9)
+#define EXYNOS_WINCON_ALPHA_MULTI_DISABLE (0 << 7)
+#define EXYNOS_WINCON_ALPHA_MULTI_ENABLE (1 << 7)
+#define EXYNOS_WINCON_BLD_PLANE (0 << 6)
+#define EXYNOS_WINCON_BLD_PIXEL (1 << 6)
+#define EXYNOS_WINCON_BLD_MASK (1 << 6)
+#define EXYNOS_WINCON_BPPMODE_1BPP (0 << 2)
+#define EXYNOS_WINCON_BPPMODE_2BPP (1 << 2)
+#define EXYNOS_WINCON_BPPMODE_4BPP (2 << 2)
+#define EXYNOS_WINCON_BPPMODE_8BPP_PAL (3 << 2)
+#define EXYNOS_WINCON_BPPMODE_8BPP (4 << 2)
+#define EXYNOS_WINCON_BPPMODE_16BPP_565 (5 << 2)
+#define EXYNOS_WINCON_BPPMODE_16BPP_A555 (6 << 2)
+#define EXYNOS_WINCON_BPPMODE_18BPP_666 (8 << 2)
+#define EXYNOS_WINCON_BPPMODE_18BPP_A665 (9 << 2)
+#define EXYNOS_WINCON_BPPMODE_24BPP_888 (0xb << 2)
+#define EXYNOS_WINCON_BPPMODE_24BPP_A887 (0xc << 2)
+#define EXYNOS_WINCON_BPPMODE_32BPP (0xd << 2)
+#define EXYNOS_WINCON_BPPMODE_16BPP_A444 (0xe << 2)
+#define EXYNOS_WINCON_BPPMODE_15BPP_555 (0xf << 2)
+#define EXYNOS_WINCON_BPPMODE_MASK (0xf << 2)
+#define EXYNOS_WINCON_BPPMODE_SHIFT (2)
+#define EXYNOS_WINCON_ALPHA0_SEL (0 << 1)
+#define EXYNOS_WINCON_ALPHA1_SEL (1 << 1)
+#define EXYNOS_WINCON_ALPHA_SEL_MASK (1 << 1)
+#define EXYNOS_WINCON_ENWIN_DISABLE (0 << 0)
+#define EXYNOS_WINCON_ENWIN_ENABLE (1 << 0)
+
+/* WINCON1 special */
+#define EXYNOS_WINCON1_VP_DISABLE (0 << 24)
+#define EXYNOS_WINCON1_VP_ENABLE (1 << 24)
+#define EXYNOS_WINCON1_LOCALSEL_FIMC1 (0 << 23)
+#define EXYNOS_WINCON1_LOCALSEL_VP (1 << 23)
+#define EXYNOS_WINCON1_LOCALSEL_MASK (1 << 23)
+
+/* WINSHMAP */
+#define EXYNOS_WINSHMAP_PROTECT(x) (((x) & 0x1f) << 10)
+#define EXYNOS_WINSHMAP_CH_ENABLE(x) (1 << (x))
+#define EXYNOS_WINSHMAP_CH_DISABLE(x) (1 << (x))
+#define EXYNOS_WINSHMAP_LOCAL_ENABLE(x) (0x20 << (x))
+#define EXYNOS_WINSHMAP_LOCAL_DISABLE(x) (0x20 << (x))
+
+/* VIDOSDxA, VIDOSDxB */
+#define EXYNOS_VIDOSD_LEFT_X(x) (((x) & 0x7ff) << 11)
+#define EXYNOS_VIDOSD_TOP_Y(x) (((x) & 0x7ff) << 0)
+#define EXYNOS_VIDOSD_RIGHT_X(x) (((x) & 0x7ff) << 11)
+#define EXYNOS_VIDOSD_BOTTOM_Y(x) (((x) & 0x7ff) << 0)
+#define EXYNOS_VIDOSD_RIGHT_X_E(x) (((x) & 0x1) << 23)
+#define EXYNOS_VIDOSD_BOTTOM_Y_E(x) (((x) & 0x1) << 22)
+
+/* VIDOSD0C, VIDOSDxD */
+#define EXYNOS_VIDOSD_SIZE(x) (((x) & 0xffffff) << 0)
+
+/* VIDOSDxC (1~4) */
+#define EXYNOS_VIDOSD_ALPHA0_R(x) (((x) & 0xf) << 20)
+#define EXYNOS_VIDOSD_ALPHA0_G(x) (((x) & 0xf) << 16)
+#define EXYNOS_VIDOSD_ALPHA0_B(x) (((x) & 0xf) << 12)
+#define EXYNOS_VIDOSD_ALPHA1_R(x) (((x) & 0xf) << 8)
+#define EXYNOS_VIDOSD_ALPHA1_G(x) (((x) & 0xf) << 4)
+#define EXYNOS_VIDOSD_ALPHA1_B(x) (((x) & 0xf) << 0)
+#define EXYNOS_VIDOSD_ALPHA0_SHIFT (12)
+#define EXYNOS_VIDOSD_ALPHA1_SHIFT (0)
+
+/* Start Address */
+#define EXYNOS_VIDADDR_START_VBANK(x) (((x) & 0xff) << 24)
+#define EXYNOS_VIDADDR_START_VBASEU(x) (((x) & 0xffffff) << 0)
+
+/* End Address */
+#define EXYNOS_VIDADDR_END_VBASEL(x) (((x) & 0xffffff) << 0)
+
+/* Buffer Size */
+#define EXYNOS_VIDADDR_OFFSIZE(x) (((x) & 0x1fff) << 13)
+#define EXYNOS_VIDADDR_PAGEWIDTH(x) (((x) & 0x1fff) << 0)
+#define EXYNOS_VIDADDR_OFFSIZE_E(x) ((((x) & 0x2000) >> 13) << 27)
+#define EXYNOS_VIDADDR_PAGEWIDTH_E(x) ((((x) & 0x2000) >> 13) << 26)
+
+/* WIN Color Map */
+#define EXYNOS_WINMAP_COLOR(x) ((x) & 0xffffff)
+
+/* VIDINTCON0 */
+#define EXYNOS_VIDINTCON0_SYSMAINCON_DISABLE (0 << 19)
+#define EXYNOS_VIDINTCON0_SYSMAINCON_ENABLE (1 << 19)
+#define EXYNOS_VIDINTCON0_SYSSUBCON_DISABLE (0 << 18)
+#define EXYNOS_VIDINTCON0_SYSSUBCON_ENABLE (1 << 18)
+#define EXYNOS_VIDINTCON0_SYSIFDONE_DISABLE (0 << 17)
+#define EXYNOS_VIDINTCON0_SYSIFDONE_ENABLE (1 << 17)
+#define EXYNOS_VIDINTCON0_FRAMESEL0_BACK (0 << 15)
+#define EXYNOS_VIDINTCON0_FRAMESEL0_VSYNC (1 << 15)
+#define EXYNOS_VIDINTCON0_FRAMESEL0_ACTIVE (2 << 15)
+#define EXYNOS_VIDINTCON0_FRAMESEL0_FRONT (3 << 15)
+#define EXYNOS_VIDINTCON0_FRAMESEL0_MASK (3 << 15)
+#define EXYNOS_VIDINTCON0_FRAMESEL1_NONE (0 << 13)
+#define EXYNOS_VIDINTCON0_FRAMESEL1_BACK (1 << 13)
+#define EXYNOS_VIDINTCON0_FRAMESEL1_VSYNC (2 << 13)
+#define EXYNOS_VIDINTCON0_FRAMESEL1_FRONT (3 << 13)
+#define EXYNOS_VIDINTCON0_INTFRMEN_DISABLE (0 << 12)
+#define EXYNOS_VIDINTCON0_INTFRMEN_ENABLE (1 << 12)
+#define EXYNOS_VIDINTCON0_FIFOSEL_WIN4 (1 << 11)
+#define EXYNOS_VIDINTCON0_FIFOSEL_WIN3 (1 << 10)
+#define EXYNOS_VIDINTCON0_FIFOSEL_WIN2 (1 << 9)
+#define EXYNOS_VIDINTCON0_FIFOSEL_WIN1 (1 << 6)
+#define EXYNOS_VIDINTCON0_FIFOSEL_WIN0 (1 << 5)
+#define EXYNOS_VIDINTCON0_FIFOSEL_ALL (0x73 << 5)
+#define EXYNOS_VIDINTCON0_FIFOSEL_MASK (0x73 << 5)
+#define EXYNOS_VIDINTCON0_FIFOLEVEL_25 (0 << 2)
+#define EXYNOS_VIDINTCON0_FIFOLEVEL_50 (1 << 2)
+#define EXYNOS_VIDINTCON0_FIFOLEVEL_75 (2 << 2)
+#define EXYNOS_VIDINTCON0_FIFOLEVEL_EMPTY (3 << 2)
+#define EXYNOS_VIDINTCON0_FIFOLEVEL_FULL (4 << 2)
+#define EXYNOS_VIDINTCON0_FIFOLEVEL_MASK (7 << 2)
+#define EXYNOS_VIDINTCON0_INTFIFO_DISABLE (0 << 1)
+#define EXYNOS_VIDINTCON0_INTFIFO_ENABLE (1 << 1)
+#define EXYNOS_VIDINTCON0_INT_DISABLE (0 << 0)
+#define EXYNOS_VIDINTCON0_INT_ENABLE (1 << 0)
+#define EXYNOS_VIDINTCON0_INT_MASK (1 << 0)
+
+/* VIDINTCON1 */
+#define EXYNOS_VIDINTCON1_INTVPPEND (1 << 5)
+#define EXYNOS_VIDINTCON1_INTI80PEND (1 << 2)
+#define EXYNOS_VIDINTCON1_INTFRMPEND (1 << 1)
+#define EXYNOS_VIDINTCON1_INTFIFOPEND (1 << 0)
+
+/* WINMAP */
+#define EXYNOS_WINMAP_ENABLE (1 << 24)
+
+/* WxKEYCON0 (1~4) */
+#define EXYNOS_KEYCON0_KEYBLEN_DISABLE (0 << 26)
+#define EXYNOS_KEYCON0_KEYBLEN_ENABLE (1 << 26)
+#define EXYNOS_KEYCON0_KEY_DISABLE (0 << 25)
+#define EXYNOS_KEYCON0_KEY_ENABLE (1 << 25)
+#define EXYNOS_KEYCON0_DIRCON_MATCH_FG (0 << 24)
+#define EXYNOS_KEYCON0_DIRCON_MATCH_BG (1 << 24)
+#define EXYNOS_KEYCON0_COMPKEY(x) (((x) & 0xffffff) << 0)
+
+/* WxKEYCON1 (1~4) */
+#define EXYNOS_KEYCON1_COLVAL(x) (((x) & 0xffffff) << 0)
+
+/* DUALRGB */
+#define EXYNOS_DUALRGB_BYPASS_SINGLE (0x00 << 0)
+#define EXYNOS_DUALRGB_BYPASS_DUAL (0x01 << 0)
+#define EXYNOS_DUALRGB_MIE_DUAL (0x10 << 0)
+#define EXYNOS_DUALRGB_MIE_SINGLE (0x11 << 0)
+#define EXYNOS_DUALRGB_LINESPLIT (0x0 << 2)
+#define EXYNOS_DUALRGB_FRAMESPLIT (0x1 << 2)
+#define EXYNOS_DUALRGB_SUB_CNT(x) ((x & 0xfff) << 4)
+#define EXYNOS_DUALRGB_VDEN_EN_DISABLE (0x0 << 16)
+#define EXYNOS_DUALRGB_VDEN_EN_ENABLE (0x1 << 16)
+#define EXYNOS_DUALRGB_MAIN_CNT(x) ((x & 0xfff) << 18)
+
+/* I80IFCONA0 and I80IFCONA1 */
+#define EXYNOS_LCD_CS_SETUP(x) (((x) & 0xf) << 16)
+#define EXYNOS_LCD_WR_SETUP(x) (((x) & 0xf) << 12)
+#define EXYNOS_LCD_WR_ACT(x) (((x) & 0xf) << 8)
+#define EXYNOS_LCD_WR_HOLD(x) (((x) & 0xf) << 4)
+#define EXYNOS_RSPOL_LOW (0 << 2)
+#define EXYNOS_RSPOL_HIGH (1 << 2)
+#define EXYNOS_I80IFEN_DISABLE (0 << 0)
+#define EXYNOS_I80IFEN_ENABLE (1 << 0)
+
+/* TRIGCON */
+#define EXYNOS_I80SOFT_TRIG_EN (1 << 0)
+#define EXYNOS_I80START_TRIG (1 << 1)
+#define EXYNOS_I80STATUS_TRIG_DONE (1 << 2)
+
+/* DP_MIE_CLKCON */
+#define EXYNOS_DP_MIE_DISABLE (0 << 0)
+#define EXYNOS_DP_CLK_ENABLE (1 << 1)
+#define EXYNOS_MIE_CLK_ENABLE (3 << 0)
+
+#define DP_TIMEOUT_LOOP_COUNT 100
+#define MAX_CR_LOOP 5
+#define MAX_EQ_LOOP 4
+
+#define EXYNOS_DP_SUCCESS 0
+
+enum {
+ DP_DISABLE,
+ DP_ENABLE,
+};
+
+struct edp_disp_info {
+ char *name;
+ unsigned int h_total;
+ unsigned int h_res;
+ unsigned int h_sync_width;
+ unsigned int h_back_porch;
+ unsigned int h_front_porch;
+ unsigned int v_total;
+ unsigned int v_res;
+ unsigned int v_sync_width;
+ unsigned int v_back_porch;
+ unsigned int v_front_porch;
+ unsigned int v_sync_rate;
+};
+
+struct edp_link_train_info {
+ unsigned int lt_status;
+ unsigned int ep_loop;
+ unsigned int cr_loop[4];
+};
+
+struct edp_video_info {
+ unsigned int master_mode;
+ unsigned int bist_mode;
+ unsigned int bist_pattern;
+ unsigned int h_sync_polarity;
+ unsigned int v_sync_polarity;
+ unsigned int interlaced;
+ unsigned int color_space;
+ unsigned int dynamic_range;
+ unsigned int ycbcr_coeff;
+ unsigned int color_depth;
+};
+
+struct edp_device_info {
+ struct edp_disp_info disp_info;
+ struct edp_link_train_info lt_info;
+ struct edp_video_info video_info;
+
+ /*below info get from panel during training*/
+ u8 lane_bw;
+ u8 lane_cnt;
+ u8 dpcd_rev;
+ /*support enhanced frame cap */
+ u8 dpcd_efc;
+ u8 *raw_edid;
+};
+
+enum analog_power_block {
+ AUX_BLOCK,
+ CH0_BLOCK,
+ CH1_BLOCK,
+ CH2_BLOCK,
+ CH3_BLOCK,
+ ANALOG_TOTAL,
+ POWER_ALL
+};
+
+enum pll_status {
+ PLL_UNLOCKED = 0,
+ PLL_LOCKED
+};
+
+enum {
+ COLOR_RGB,
+ COLOR_YCBCR422,
+ COLOR_YCBCR444
+};
+
+enum {
+ VESA,
+ CEA
+};
+
+enum {
+ COLOR_YCBCR601,
+ COLOR_YCBCR709
+};
+
+enum {
+ COLOR_6,
+ COLOR_8,
+ COLOR_10,
+ COLOR_12
+};
+
+enum {
+ DP_LANE_BW_1_62 = 0x06,
+ DP_LANE_BW_2_70 = 0x0a,
+};
+
+enum {
+ DP_LANE_CNT_1 = 1,
+ DP_LANE_CNT_2 = 2,
+ DP_LANE_CNT_4 = 4,
+};
+
+enum {
+ DP_DPCD_REV_10 = 0x10,
+ DP_DPCD_REV_11 = 0x11,
+};
+
+enum {
+ DP_LT_NONE,
+ DP_LT_START,
+ DP_LT_CR,
+ DP_LT_ET,
+ DP_LT_FINISHED,
+ DP_LT_FAIL,
+};
+
+enum {
+ PRE_EMPHASIS_LEVEL_0,
+ PRE_EMPHASIS_LEVEL_1,
+ PRE_EMPHASIS_LEVEL_2,
+ PRE_EMPHASIS_LEVEL_3,
+};
+
+enum {
+ PRBS7,
+ D10_2,
+ TRAINING_PTN1,
+ TRAINING_PTN2,
+ DP_NONE
+};
+
+enum {
+ VOLTAGE_LEVEL_0,
+ VOLTAGE_LEVEL_1,
+ VOLTAGE_LEVEL_2,
+ VOLTAGE_LEVEL_3,
+};
+
+enum pattern_type {
+ NO_PATTERN,
+ COLOR_RAMP,
+ BALCK_WHITE_V_LINES,
+ COLOR_SQUARE,
+ INVALID_PATTERN,
+ COLORBAR_32,
+ COLORBAR_64,
+ WHITE_GRAY_BALCKBAR_32,
+ WHITE_GRAY_BALCKBAR_64,
+ MOBILE_WHITEBAR_32,
+ MOBILE_WHITEBAR_64
+};
+
+enum {
+ CALCULATED_M,
+ REGISTER_M
+};
+
+enum {
+ VIDEO_TIMING_FROM_CAPTURE,
+ VIDEO_TIMING_FROM_REGISTER
+};
+
+
+struct exynos_dp_platform_data {
+ struct edp_device_info *edp_dev_info;
+};
+
+
+int exynos_init_dp(struct edp_device_info *edp_info);
+
+void exynos_set_dp_platform_data(struct exynos_dp_platform_data *pd);
+
+void exynos_dp_disable_video_bist(void);
+void exynos_dp_enable_video_mute(unsigned int enable);
+void exynos_dp_reset(void);
+void exynos_dp_enable_sw_func(unsigned int enable);
+unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable);
+unsigned int exynos_dp_get_pll_lock_status(void);
+int exynos_dp_init_analog_func(void);
+void exynos_dp_init_hpd(void);
+void exynos_dp_init_aux(void);
+void exynos_dp_config_interrupt(void);
+unsigned int exynos_dp_get_plug_in_status(void);
+unsigned int exynos_dp_detect_hpd(void);
+unsigned int exynos_dp_start_aux_transaction(void);
+unsigned int exynos_dp_write_byte_to_dpcd(u32 reg_addr,
+ u8 data);
+unsigned int exynos_dp_read_byte_from_dpcd(u32 reg_addr,
+ u8 *data);
+unsigned int exynos_dp_write_bytes_to_dpcd(u32 reg_addr,
+ unsigned int count,
+ u8 data[]);
+u32 exynos_dp_read_bytes_from_dpcd( unsigned int reg_addr,
+ unsigned int count,
+ u8 data[]);
+int exynos_dp_select_i2c_device( u32 device_addr,
+ u32 reg_addr);
+int exynos_dp_read_byte_from_i2c(u32 device_addr,
+ u32 reg_addr, unsigned int *data);
+int exynos_dp_read_bytes_from_i2c(u32 device_addr,
+ u32 reg_addr, unsigned int count,
+ u8 edid[]);
+void exynos_dp_reset_macro(void);
+void exynos_dp_set_link_bandwidth(u8 bwtype);
+u8 exynos_dp_get_link_bandwidth(void);
+void exynos_dp_set_lane_count(u8 count);
+unsigned int exynos_dp_get_lane_count(void);
+u8 exynos_dp_get_lanex_pre_emphasis(u8 lanecnt);
+void exynos_dp_set_lane_pre_emphasis(unsigned int level,
+ u8 lanecnt);
+void exynos_dp_set_lanex_pre_emphasis(u8 request_val,
+ u8 lanecnt);
+void exynos_dp_set_training_pattern(unsigned int pattern);
+void exynos_dp_enable_enhanced_mode(u8 enable);
+void exynos_dp_enable_scrambling(unsigned int enable);
+int exynos_dp_init_video(void);
+void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info);
+void exynos_dp_set_video_color_format(struct edp_video_info *video_info);
+int exynos_dp_config_video_bist(struct edp_device_info *edp_info);
+unsigned int exynos_dp_is_slave_video_stream_clock_on(void);
+void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value,
+ unsigned int n_value);
+void exynos_dp_set_video_timing_mode(unsigned int type);
+void exynos_dp_enable_video_master(unsigned int enable);
+void exynos_dp_start_video(void);
+unsigned int exynos_dp_is_video_stream_on(void);
+void exynos_dp_set_base_addr(void);
+void dp_phy_control(unsigned int enable);
#endif
diff --git a/src/cpu/samsung/exynos5420/dp_lowlevel.c b/src/cpu/samsung/exynos5420/dp_lowlevel.c
new file mode 100644
index 0000000000..64a296258d
--- /dev/null
+++ b/src/cpu/samsung/exynos5420/dp_lowlevel.c
@@ -0,0 +1,1199 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * Author: Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <arch/io.h>
+#include <stdlib.h>
+#include <string.h>
+#include <timer.h>
+#include <delay.h>
+#include <console/console.h>
+#include "timer.h"
+#include "cpu.h"
+#include "power.h"
+#include "sysreg.h"
+#include <drivers/maxim/max77686/max77686.h>
+
+#include "device/i2c.h"
+#include "i2c.h"
+#include "fimd.h"
+#include "dp.h"
+
+/* in u-boot, there's a function you call to set a pointer
+ * to a constant. Klever!
+ */
+struct exynos_dp *dp_regs = samsung_get_base_dp();
+
+/* for debugging, it's nice to get control on a per-file basis.
+ * I had a bit of a discussion with myself (boring!) about
+ * how to do this and for the moment this is the easiest way.
+ * These debugging statements allowed me to find the final bugs.
+ */
+
+#if 0
+static inline void fwadl(unsigned long l,void *v) {
+ writel(l, v);
+ printk(BIOS_SPEW, "W %p %p\n", v, (void *)l);
+}
+#define lwrite32(a,b) fwadl((unsigned long)(a), (void *)(b))
+
+static inline unsigned long fradl(void *v) {
+ unsigned long l = readl(v);
+ printk(BIOS_SPEW, "R %p %p\n", v, (void *)l);
+ return l;
+}
+
+#define lread32(a) fradl((void *)(a))
+#else
+#define lwrite32(a,b) write32((unsigned long)(a), (void *)(b))
+#define lread32(a) read32((void *)(a))
+#endif
+
+static void exynos_dp_enable_video_input(u32 enable)
+{
+ u32 reg;
+
+ reg = lread32(&dp_regs->video_ctl1);
+ reg &= ~VIDEO_EN_MASK;
+
+ /* enable video input*/
+ if (enable)
+ reg |= VIDEO_EN_MASK;
+
+ lwrite32(reg, &dp_regs->video_ctl1);
+
+ return;
+}
+
+void exynos_dp_disable_video_bist(void)
+{
+ u32 reg;
+ reg = lread32(&dp_regs->video_ctl4);
+ reg &= ~VIDEO_BIST_MASK;
+ lwrite32(reg, &dp_regs->video_ctl4);
+}
+
+void exynos_dp_enable_video_mute(unsigned int enable)
+{
+ u32 reg;
+
+ reg = lread32(&dp_regs->video_ctl1);
+ reg &= ~(VIDEO_MUTE_MASK);
+ if (enable)
+ reg |= VIDEO_MUTE_MASK;
+
+ lwrite32(reg, &dp_regs->video_ctl1);
+
+ return;
+}
+
+
+static void exynos_dp_init_analog_param(void)
+{
+ u32 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;
+ lwrite32(reg, &dp_regs->analog_ctl1);
+
+ reg = SEL_24M | TX_DVDD_BIT_1_0625V;
+ lwrite32(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;
+ lwrite32(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;
+ lwrite32(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;
+
+ lwrite32(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;
+ lwrite32(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
+ */
+ lwrite32(INT_POL, &dp_regs->int_ctl);
+
+ /* Clear pending regisers */
+ lwrite32(0xff, &dp_regs->common_int_sta1);
+ lwrite32(0xff, &dp_regs->common_int_sta2);
+ lwrite32(0xff, &dp_regs->common_int_sta3);
+ lwrite32(0xff, &dp_regs->common_int_sta4);
+ lwrite32(0xff, &dp_regs->int_sta);
+
+ /* 0:mask,1: unmask */
+ lwrite32(0x00, &dp_regs->int_sta_mask1);
+ lwrite32(0x00, &dp_regs->int_sta_mask2);
+ lwrite32(0x00, &dp_regs->int_sta_mask3);
+ lwrite32(0x00, &dp_regs->int_sta_mask4);
+ lwrite32(0x00, &dp_regs->int_sta_mask);
+}
+
+void exynos_dp_reset(void)
+{
+ u32 reg_func_1;
+
+ /*dp tx sw reset*/
+ lwrite32(RESET_DP_TX, &dp_regs->tx_sw_reset);
+
+ exynos_dp_enable_video_input(DP_DISABLE);
+ exynos_dp_disable_video_bist();
+ 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;
+
+ lwrite32(reg_func_1, &dp_regs->func_en1);
+ lwrite32(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)
+{
+ u32 reg;
+
+ reg = lread32(&dp_regs->func_en1);
+ reg &= ~(SW_FUNC_EN_N);
+
+ if (!enable)
+ reg |= SW_FUNC_EN_N;
+
+ lwrite32(reg, &dp_regs->func_en1);
+
+ return;
+}
+
+unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable)
+{
+ u32 reg;
+
+ reg = lread32(&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:
+ printk(BIOS_ERR, "DP undefined block number : %d\n", block);
+ return -1;
+ }
+
+ lwrite32(reg, &dp_regs->phy_pd);
+
+ return 0;
+}
+
+unsigned int exynos_dp_get_pll_lock_status(void)
+{
+ u32 reg;
+
+ reg = lread32(&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)
+{
+ u32 reg;
+
+ reg = lread32(&dp_regs->pll_ctl);
+ reg &= ~(DP_PLL_PD);
+
+ if (!enable)
+ reg |= DP_PLL_PD;
+
+ lwrite32(reg, &dp_regs->pll_ctl);
+}
+
+int exynos_dp_init_analog_func(void)
+{
+ int ret = EXYNOS_DP_SUCCESS;
+ unsigned int retry_cnt = 10;
+ u32 reg;
+
+ /*Power On All Analog block */
+ exynos_dp_set_analog_power_down(POWER_ALL, DP_DISABLE);
+
+ reg = PLL_LOCK_CHG;
+ lwrite32(reg, &dp_regs->common_int_sta1);
+
+ reg = lread32(&dp_regs->debug_ctl);
+ reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
+ lwrite32(reg, &dp_regs->debug_ctl);
+
+ /*Assert DP PLL Reset*/
+ reg = lread32(&dp_regs->pll_ctl);
+ reg |= DP_PLL_RESET;
+ lwrite32(reg, &dp_regs->pll_ctl);
+
+ mdelay(1);
+
+ /*Deassert DP PLL Reset*/
+ reg = lread32(&dp_regs->pll_ctl);
+ reg &= ~(DP_PLL_RESET);
+ lwrite32(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) {
+ printk(BIOS_ERR, "DP dp's pll lock failed : retry : %d\n",
+ retry_cnt);
+ return -1;
+ }
+ }
+
+ printk(BIOS_DEBUG, "dp's pll lock success(%d)\n", retry_cnt);
+
+ /* Enable Serdes FIFO function and Link symbol clock domain module */
+ reg = lread32(&dp_regs->func_en2);
+ reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
+ | AUX_FUNC_EN_N);
+ lwrite32(reg, &dp_regs->func_en2);
+
+ return ret;
+}
+
+void exynos_dp_init_hpd(void)
+{
+ u32 reg;
+
+ /* Clear interrupts releated to Hot Plug Dectect */
+ reg = HOTPLUG_CHG | HPD_LOST | PLUG;
+ lwrite32(reg, &dp_regs->common_int_sta4);
+
+ reg = INT_HPD;
+ lwrite32(reg, &dp_regs->int_sta);
+
+ reg = lread32(&dp_regs->sys_ctl3);
+ reg &= ~(F_HPD | HPD_CTRL);
+ lwrite32(reg, &dp_regs->sys_ctl3);
+
+ return;
+}
+
+static inline void exynos_dp_reset_aux(void)
+{
+ u32 reg;
+
+ /* Disable AUX channel module */
+ reg = lread32(&dp_regs->func_en2);
+ reg |= AUX_FUNC_EN_N;
+ lwrite32(reg, &dp_regs->func_en2);
+
+ return;
+}
+
+void exynos_dp_init_aux(void)
+{
+ u32 reg;
+
+ /* Clear inerrupts related to AUX channel */
+ reg = RPLY_RECEIV | AUX_ERR;
+ lwrite32(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;
+ lwrite32(reg, &dp_regs->aux_hw_retry_ctl);
+
+ /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
+ reg = DEFER_CTRL_EN | DEFER_COUNT(1);
+ lwrite32(reg, &dp_regs->aux_ch_defer_ctl);
+
+ /* Enable AUX channel module */
+ reg = lread32(&dp_regs->func_en2);
+ reg &= ~AUX_FUNC_EN_N;
+ lwrite32(reg, &dp_regs->func_en2);
+
+ return;
+}
+
+void exynos_dp_config_interrupt(void)
+{
+ u32 reg;
+
+ /* 0: mask, 1: unmask */
+ reg = COMMON_INT_MASK_1;
+ lwrite32(reg, &dp_regs->common_int_mask1);
+
+ reg = COMMON_INT_MASK_2;
+ lwrite32(reg, &dp_regs->common_int_mask2);
+
+ reg = COMMON_INT_MASK_3;
+ lwrite32(reg, &dp_regs->common_int_mask3);
+
+ reg = COMMON_INT_MASK_4;
+ lwrite32(reg, &dp_regs->common_int_mask4);
+
+ reg = INT_STA_MASK;
+ lwrite32(reg, &dp_regs->int_sta_mask);
+
+ return;
+}
+
+unsigned int exynos_dp_get_plug_in_status(void)
+{
+ u32 reg;
+
+ reg = lread32(&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 -1;
+ mdelay(10);
+ timeout_loop--;
+ }
+
+ return EXYNOS_DP_SUCCESS;
+}
+
+unsigned int exynos_dp_start_aux_transaction(void)
+{
+ u32 reg;
+ unsigned int ret = 0;
+ unsigned int retry_cnt;
+
+ /* Enable AUX CH operation */
+ reg = lread32(&dp_regs->aux_ch_ctl2);
+ reg |= AUX_EN;
+ lwrite32(reg, &dp_regs->aux_ch_ctl2);
+
+ retry_cnt = 10;
+ while (retry_cnt) {
+ reg = lread32(&dp_regs->int_sta);
+ if (!(reg & RPLY_RECEIV)) {
+ if (retry_cnt == 0) {
+ printk(BIOS_ERR, "DP Reply Timeout!!\n");
+ ret = -1;
+ return ret;
+ }
+ mdelay(1);
+ retry_cnt--;
+ } else
+ break;
+ }
+
+ /* Clear interrupt source for AUX CH command reply */
+ lwrite32(reg, &dp_regs->int_sta);
+
+ /* Clear interrupt source for AUX CH access error */
+ reg = lread32(&dp_regs->int_sta);
+ if (reg & AUX_ERR) {
+ printk(BIOS_ERR, "DP Aux Access Error\n");
+ lwrite32(AUX_ERR, &dp_regs->int_sta);
+ ret = -1;
+ return ret;
+ }
+
+ /* Check AUX CH error access status */
+ reg = lread32(&dp_regs->aux_ch_sta);
+ if ((reg & AUX_STATUS_MASK) != 0) {
+ printk(BIOS_DEBUG, "DP AUX CH error happens: %x\n", reg & AUX_STATUS_MASK);
+ ret = -1;
+ return ret;
+ }
+ return EXYNOS_DP_SUCCESS;
+}
+
+unsigned int exynos_dp_write_byte_to_dpcd(u32 reg_addr, u8 data)
+{
+ u32 reg;
+ unsigned int ret;
+
+ /* Clear AUX CH data buffer */
+ reg = BUF_CLR;
+ lwrite32(reg, &dp_regs->buffer_data_ctl);
+
+ /* Select DPCD device address */
+ reg = AUX_ADDR_7_0(reg_addr);
+ lwrite32(reg, &dp_regs->aux_addr_7_0);
+ reg = AUX_ADDR_15_8(reg_addr);
+ lwrite32(reg, &dp_regs->aux_addr_15_8);
+ reg = AUX_ADDR_19_16(reg_addr);
+ lwrite32(reg, &dp_regs->aux_addr_19_16);
+
+ /* Write data buffer */
+ reg = data;
+ lwrite32(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;
+ lwrite32(reg, &dp_regs->aux_ch_ctl1);
+
+ /* Start AUX transaction */
+ ret = exynos_dp_start_aux_transaction();
+ if (ret != EXYNOS_DP_SUCCESS) {
+ printk(BIOS_ERR, "DP Aux transaction failed\n");
+ }
+
+ return ret;
+}
+
+unsigned int exynos_dp_read_byte_from_dpcd(u32 reg_addr,
+ unsigned char *data)
+{
+ u32 reg;
+ int retval;
+
+ /* Clear AUX CH data buffer */
+ reg = BUF_CLR;
+ lwrite32(reg, &dp_regs->buffer_data_ctl);
+
+ /* Select DPCD device address */
+ reg = AUX_ADDR_7_0(reg_addr);
+ lwrite32(reg, &dp_regs->aux_addr_7_0);
+ reg = AUX_ADDR_15_8(reg_addr);
+ lwrite32(reg, &dp_regs->aux_addr_15_8);
+ reg = AUX_ADDR_19_16(reg_addr);
+ lwrite32(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;
+ lwrite32(reg, &dp_regs->aux_ch_ctl1);
+
+ /* Start AUX transaction */
+ retval = exynos_dp_start_aux_transaction();
+ if (retval != EXYNOS_DP_SUCCESS)
+ printk(BIOS_DEBUG, "DP Aux Transaction fail!\n");
+
+ /* Read data buffer */
+ reg = lread32(&dp_regs->buf_data0);
+ *data = (unsigned char)(reg & 0xff);
+
+ return retval;
+}
+
+unsigned int exynos_dp_write_bytes_to_dpcd(u32 reg_addr,
+ unsigned int count,
+ unsigned char data[])
+{
+ u32 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;
+ lwrite32(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);
+ lwrite32(reg, &dp_regs->aux_addr_7_0);
+ reg = AUX_ADDR_15_8(reg_addr + start_offset);
+ lwrite32(reg, &dp_regs->aux_addr_15_8);
+ reg = AUX_ADDR_19_16(reg_addr + start_offset);
+ lwrite32(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];
+ lwrite32(reg, (void *)((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;
+ lwrite32(reg, &dp_regs->aux_ch_ctl1);
+
+ /* Start AUX transaction */
+ ret = exynos_dp_start_aux_transaction();
+ if (ret != EXYNOS_DP_SUCCESS) {
+ if (retry_cnt == 0) {
+ printk(BIOS_ERR, "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(u32 reg_addr,
+ unsigned int count,
+ unsigned char data[])
+{
+ u32 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;
+ lwrite32(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);
+ lwrite32(reg, &dp_regs->aux_addr_7_0);
+ reg = AUX_ADDR_15_8(reg_addr + start_offset);
+ lwrite32(reg, &dp_regs->aux_addr_15_8);
+ reg = AUX_ADDR_19_16(reg_addr + start_offset);
+ lwrite32(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;
+ lwrite32(reg, &dp_regs->aux_ch_ctl1);
+
+ /* Start AUX transaction */
+ ret = exynos_dp_start_aux_transaction();
+ if (ret != EXYNOS_DP_SUCCESS) {
+ if (retry_cnt == 0) {
+ printk(BIOS_ERR, "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 = lread32((void *)((u32)&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(u32 device_addr,
+ u32 reg_addr)
+{
+ u32 reg;
+ int retval;
+
+ /* Set EDID device address */
+ reg = device_addr;
+ lwrite32(reg, &dp_regs->aux_addr_7_0);
+ lwrite32(0x0, &dp_regs->aux_addr_15_8);
+ lwrite32(0x0, &dp_regs->aux_addr_19_16);
+
+ /* Set offset from base address of EDID device */
+ lwrite32(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;
+ lwrite32(reg, &dp_regs->aux_ch_ctl1);
+
+ /* Start AUX transaction */
+ retval = exynos_dp_start_aux_transaction();
+ if (retval != 0)
+ printk(BIOS_DEBUG, "%s: DP Aux Transaction fail!\n", __func__);
+
+ return retval;
+}
+
+int exynos_dp_read_byte_from_i2c(u32 device_addr,
+ u32 reg_addr,
+ unsigned int *data)
+{
+ u32 reg;
+ int i;
+ int retval;
+
+ for (i = 0; i < 10; i++) {
+ /* Clear AUX CH data buffer */
+ reg = BUF_CLR;
+ lwrite32(reg, &dp_regs->buffer_data_ctl);
+
+ /* Select EDID device */
+ retval = exynos_dp_select_i2c_device(device_addr, reg_addr);
+ if (retval != 0) {
+ printk(BIOS_DEBUG, "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;
+ lwrite32(reg, &dp_regs->aux_ch_ctl1);
+
+ /* Start AUX transaction */
+ retval = exynos_dp_start_aux_transaction();
+ if (retval != EXYNOS_DP_SUCCESS)
+ printk(BIOS_DEBUG, "%s: DP Aux Transaction fail!\n", __func__);
+ }
+
+ /* Read data */
+ if (retval == 0)
+ *data = lread32(&dp_regs->buf_data0);
+
+ return retval;
+}
+
+int exynos_dp_read_bytes_from_i2c(u32 device_addr,
+ u32 reg_addr, unsigned int count, unsigned char edid[])
+{
+ u32 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;
+ lwrite32(reg, &dp_regs->buffer_data_ctl);
+
+ /* Set normal AUX CH command */
+ reg = lread32(&dp_regs->aux_ch_ctl2);
+ reg &= ~ADDR_ONLY;
+ lwrite32(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;
+ lwrite32(reg, &dp_regs->aux_ch_ctl1);
+
+ /* Start AUX transaction */
+ retval = exynos_dp_start_aux_transaction();
+ if (retval == 0)
+ break;
+ else
+ printk(BIOS_ERR, "DP Aux Transaction fail!\n");
+ }
+ /* Check if Rx sends defer */
+ reg = lread32(&dp_regs->aux_rx_comm);
+ if (reg == AUX_RX_COMM_AUX_DEFER ||
+ reg == AUX_RX_COMM_I2C_DEFER) {
+ printk(BIOS_ERR, "DP Defer: %d\n\n", reg);
+ defer = 1;
+ }
+ }
+
+ for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
+ reg = lread32((void *)((u32)&dp_regs->buf_data0
+ + 4 * cur_data_idx));
+ edid[i + cur_data_idx] = (unsigned char)reg;
+ }
+ }
+
+ return retval;
+}
+
+void exynos_dp_reset_macro(void)
+{
+ u32 reg;
+
+ reg = lread32(&dp_regs->phy_test);
+ reg |= MACRO_RST;
+ lwrite32(reg, &dp_regs->phy_test);
+
+ /* 10 us is the minimum Macro reset time. */
+ mdelay(1);
+
+ reg &= ~MACRO_RST;
+ lwrite32(reg, &dp_regs->phy_test);
+}
+
+void exynos_dp_set_link_bandwidth(unsigned char bwtype)
+{
+ u32 reg;
+
+ reg = (u32)bwtype;
+
+ /* Set bandwidth to 2.7G or 1.62G */
+ if ((bwtype == DP_LANE_BW_1_62) || (bwtype == DP_LANE_BW_2_70))
+ lwrite32(reg, &dp_regs->link_bw_set);
+}
+
+unsigned char exynos_dp_get_link_bandwidth(void)
+{
+ unsigned char ret;
+ u32 reg;
+
+ reg = lread32(&dp_regs->link_bw_set);
+ ret = (unsigned char)reg;
+
+ return ret;
+}
+
+void exynos_dp_set_lane_count(unsigned char count)
+{
+ u32 reg;
+
+ reg = (u32)count;
+
+ if ((count == DP_LANE_CNT_1) || (count == DP_LANE_CNT_2) ||
+ (count == DP_LANE_CNT_4))
+ lwrite32(reg, &dp_regs->lane_count_set);
+}
+
+unsigned int exynos_dp_get_lane_count(void)
+{
+ u32 reg;
+
+ reg = lread32(&dp_regs->lane_count_set);
+
+ return reg;
+}
+
+unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt)
+{
+ void *reg_list[DP_LANE_CNT_4] = {
+ &dp_regs->ln0_link_training_ctl,
+ &dp_regs->ln1_link_training_ctl,
+ &dp_regs->ln2_link_training_ctl,
+ &dp_regs->ln3_link_training_ctl,
+ };
+
+ return lread32(reg_list[lanecnt]);
+}
+
+void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val,
+ unsigned char lanecnt)
+{
+ void * reg_list[DP_LANE_CNT_4] = {
+ &dp_regs->ln0_link_training_ctl,
+ &dp_regs->ln1_link_training_ctl,
+ &dp_regs->ln2_link_training_ctl,
+ &dp_regs->ln3_link_training_ctl,
+ };
+
+ lwrite32(request_val, reg_list[lanecnt]);
+}
+
+void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt)
+{
+ unsigned char i;
+ u32 reg;
+ void *reg_list[DP_LANE_CNT_4] = {
+ &dp_regs->ln0_link_training_ctl,
+ &dp_regs->ln1_link_training_ctl,
+ &dp_regs->ln2_link_training_ctl,
+ &dp_regs->ln3_link_training_ctl,
+ };
+ u32 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];
+ lwrite32(reg, reg_list[i]);
+ }
+}
+
+void exynos_dp_set_training_pattern(unsigned int pattern)
+{
+ u32 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;
+ }
+
+ lwrite32(reg, &dp_regs->training_ptn_set);
+}
+
+void exynos_dp_enable_enhanced_mode(unsigned char enable)
+{
+ u32 reg;
+
+ reg = lread32(&dp_regs->sys_ctl4);
+ reg &= ~ENHANCED;
+
+ if (enable)
+ reg |= ENHANCED;
+
+ lwrite32(reg, &dp_regs->sys_ctl4);
+}
+
+void exynos_dp_enable_scrambling(unsigned int enable)
+{
+ u32 reg;
+
+ reg = lread32(&dp_regs->training_ptn_set);
+ reg &= ~(SCRAMBLING_DISABLE);
+
+ if (!enable)
+ reg |= SCRAMBLING_DISABLE;
+
+ lwrite32(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;
+ lwrite32(reg, &dp_regs->common_int_sta1);
+
+ /* I_STRM__CLK detect : DE_CTL : Auto detect */
+ reg &= ~DET_CTRL;
+ lwrite32(reg, &dp_regs->sys_ctl1);
+ return 0;
+}
+
+
+void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info)
+{
+ u32 reg;
+
+ /* Video Slave mode setting */
+ reg = lread32(&dp_regs->func_en1);
+ reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
+ reg |= MASTER_VID_FUNC_EN_N;
+ lwrite32(reg, &dp_regs->func_en1);
+
+ /* Configure Interlaced for slave mode video */
+ reg = lread32(&dp_regs->video_ctl10);
+ reg &= ~INTERACE_SCAN_CFG;
+ reg |= (video_info->interlaced << INTERACE_SCAN_CFG_SHIFT);
+ printk(BIOS_SPEW, "interlaced %d\n", video_info->interlaced);
+ lwrite32(reg, &dp_regs->video_ctl10);
+
+ /* Configure V sync polarity for slave mode video */
+ reg = lread32(&dp_regs->video_ctl10);
+ reg &= ~VSYNC_POLARITY_CFG;
+ reg |= (video_info->v_sync_polarity << V_S_POLARITY_CFG_SHIFT);
+ lwrite32(reg, &dp_regs->video_ctl10);
+
+ /* Configure H sync polarity for slave mode video */
+ reg = lread32(&dp_regs->video_ctl10);
+ reg &= ~HSYNC_POLARITY_CFG;
+ reg |= (video_info->h_sync_polarity << H_S_POLARITY_CFG_SHIFT);
+ lwrite32(reg, &dp_regs->video_ctl10);
+
+ /*Set video mode to slave mode */
+ reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
+ lwrite32(reg, &dp_regs->soc_general_ctl);
+}
+
+void exynos_dp_set_video_color_format(struct edp_video_info *video_info)
+{
+ u32 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);
+ lwrite32(reg, &dp_regs->video_ctl2);
+
+ /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
+ reg = lread32(&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;
+ lwrite32(reg, &dp_regs->video_ctl3);
+}
+
+unsigned int exynos_dp_is_slave_video_stream_clock_on(void)
+{
+ u32 reg;
+
+ /* Update Video stream clk detect status */
+ reg = lread32(&dp_regs->sys_ctl1);
+ lwrite32(reg, &dp_regs->sys_ctl1);
+
+ reg = lread32(&dp_regs->sys_ctl1);
+
+ if (!(reg & DET_STA)) {
+ printk(BIOS_DEBUG, "DP Input stream clock not detected.\n");
+ return -1;
+ }
+
+ return EXYNOS_DP_SUCCESS;
+}
+
+void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value,
+ unsigned int n_value)
+{
+ u32 reg;
+
+ if (type == REGISTER_M) {
+ reg = lread32(&dp_regs->sys_ctl4);
+ reg |= FIX_M_VID;
+ lwrite32(reg, &dp_regs->sys_ctl4);
+ reg = M_VID0_CFG(m_value);
+ lwrite32(reg, &dp_regs->m_vid0);
+ reg = M_VID1_CFG(m_value);
+ lwrite32(reg, &dp_regs->m_vid1);
+ reg = M_VID2_CFG(m_value);
+ lwrite32(reg, &dp_regs->m_vid2);
+
+ reg = N_VID0_CFG(n_value);
+ lwrite32(reg, &dp_regs->n_vid0);
+ reg = N_VID1_CFG(n_value);
+ lwrite32(reg, &dp_regs->n_vid1);
+ reg = N_VID2_CFG(n_value);
+ lwrite32(reg, &dp_regs->n_vid2);
+ } else {
+ reg = lread32(&dp_regs->sys_ctl4);
+ reg &= ~FIX_M_VID;
+ lwrite32(reg, &dp_regs->sys_ctl4);
+ }
+}
+
+void exynos_dp_set_video_timing_mode(unsigned int type)
+{
+ u32 reg;
+
+ reg = lread32(&dp_regs->video_ctl10);
+ reg &= ~FORMAT_SEL;
+
+ if (type != VIDEO_TIMING_FROM_CAPTURE)
+ reg |= FORMAT_SEL;
+
+ lwrite32(reg, &dp_regs->video_ctl10);
+}
+
+void exynos_dp_enable_video_master(unsigned int enable)
+{
+ u32 reg;
+
+ reg = lread32(&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;
+ }
+
+ lwrite32(reg, &dp_regs->soc_general_ctl);
+}
+
+void exynos_dp_start_video(void)
+{
+ u32 reg;
+
+ /* Enable Video input and disable Mute */
+ reg = lread32(&dp_regs->video_ctl1);
+ reg |= VIDEO_EN;
+ lwrite32(reg, &dp_regs->video_ctl1);
+}
+
+unsigned int exynos_dp_is_video_stream_on(void)
+{
+ u32 reg;
+
+ /* Update STRM_VALID */
+ reg = lread32(&dp_regs->sys_ctl3);
+ lwrite32(reg, &dp_regs->sys_ctl3);
+
+ reg = lread32(&dp_regs->sys_ctl3);
+
+ if (!(reg & STRM_VALID))
+ return -1;
+
+ return EXYNOS_DP_SUCCESS;
+}
+
+void dp_phy_control(unsigned int enable)
+{
+ u32 cfg;
+ struct exynos5_power *power = samsung_get_base_power();
+
+ cfg = lread32(&power->dptx_phy_control);
+ if (enable)
+ cfg |= EXYNOS_DP_PHY_ENABLE;
+ else
+ cfg &= ~EXYNOS_DP_PHY_ENABLE;
+ lwrite32(cfg, &power->dptx_phy_control);
+}
diff --git a/src/cpu/samsung/exynos5420/fb.c b/src/cpu/samsung/exynos5420/fb.c
deleted file mode 100644
index 3724a247c6..0000000000
--- a/src/cpu/samsung/exynos5420/fb.c
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2013 Google Inc.
- * Copyright (C) 2012 Samsung Electronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/* LCD driver for Exynos */
-
-#include <arch/io.h>
-#include <stdlib.h>
-#include <string.h>
-#include <timer.h>
-#include <delay.h>
-#include <console/console.h>
-#include "cpu.h"
-#include "power.h"
-#include "sysreg.h"
-#include <drivers/maxim/max77686/max77686.h>
-
-#include "device/i2c.h"
-#include "i2c.h"
-#include "fimd.h"
-#include "dp.h"
-#include "dp-core.h"
-
-/*
- * Here is the rough outline of how we bring up the display:
- * 1. Upon power-on Sink generates a hot plug detection pulse thru HPD
- * 2. Source determines video mode by reading DPCD receiver capability field
- * (DPCD 00000h to 0000Dh) including eDP CP capability register (DPCD
- * 0000Dh).
- * 3. Sink replies DPCD receiver capability field.
- * 4. Source starts EDID read thru I2C-over-AUX.
- * 5. Sink replies EDID thru I2C-over-AUX.
- * 6. Source determines link configuration, such as MAX_LINK_RATE and
- * MAX_LANE_COUNT. Source also determines which type of eDP Authentication
- * method to use and writes DPCD link configuration field (DPCD 00100h to
- * 0010Ah) including eDP configuration set (DPCD 0010Ah).
- * 7. Source starts link training. Sink does clock recovery and equalization.
- * 8. Source reads DPCD link status field (DPCD 00200h to 0020Bh).
- * 9. Sink replies DPCD link status field. If main link is not stable, Source
- * repeats Step 7.
- * 10. Source sends MSA (Main Stream Attribute) data. Sink extracts video
- * parameters and recovers stream clock.
- * 11. Source sends video data.
- */
-
-/* To help debug any init errors here, define a list of possible errors */
-enum {
- ERR_PLL_NOT_UNLOCKED = 2,
- ERR_VIDEO_CLOCK_BAD,
- ERR_VIDEO_STREAM_BAD,
- ERR_DPCD_READ_ERROR1, /* 5 */
-
- ERR_DPCD_WRITE_ERROR1,
- ERR_DPCD_READ_ERROR2,
- ERR_DPCD_WRITE_ERROR2,
- ERR_INVALID_LANE,
- ERR_PLL_NOT_LOCKED, /* 10 */
-
- ERR_PRE_EMPHASIS_LEVELS,
- ERR_LINK_RATE_ABNORMAL,
- ERR_MAX_LANE_COUNT_ABNORMAL,
- ERR_LINK_TRAINING_FAILURE,
- ERR_MISSING_DP_BASE, /* 15 */
-
- ERR_NO_FDT_NODE,
-};
-/* ok, this is stupid, but we're going to leave the variables in here until we
- * know it works. One cleanup task at a time.
- */
-enum stage_t {
- STAGE_START = 0,
- STAGE_LCD_VDD,
- STAGE_BRIDGE_SETUP,
- STAGE_BRIDGE_INIT,
- STAGE_BRIDGE_RESET,
- STAGE_HOTPLUG,
- STAGE_DP_CONTROLLER,
- STAGE_BACKLIGHT_VDD,
- STAGE_BACKLIGHT_PWM,
- STAGE_BACKLIGHT_EN,
- STAGE_DONE,
-};
-
-int lcd_line_length;
-int lcd_color_fg;
-int lcd_color_bg;
-
-void *lcd_console_address; /* Start of console buffer */
-
-short console_col;
-short console_row;
-
-/* Bypass FIMD of DISP1_BLK */
-static void fimd_bypass(void)
-{
- struct exynos5_sysreg *sysreg = samsung_get_base_sysreg();
-
- setbits_le32(&sysreg->disp1blk_cfg, FIMDBYPASS_DISP1);
- sysreg->disp1blk_cfg &= ~FIMDBYPASS_DISP1;
-}
-
-/*
- * Initialize display controller.
- *
- * @param lcdbase pointer to the base address of framebuffer.
- * @pd pointer to the main panel_data structure
- */
-void fb_init(unsigned long int fb_size, void *lcdbase,
- struct exynos5_fimd_panel *pd)
-{
- unsigned int val;
- struct exynos5_fimd *fimd = samsung_get_base_fimd();
- struct exynos5_disp_ctrl *disp_ctrl = samsung_get_base_disp_ctrl();
-
- fb_size = ALIGN(fb_size, 4096);
-
- writel(pd->ivclk | pd->fixvclk, &disp_ctrl->vidcon1);
- val = ENVID_ON | ENVID_F_ON | (pd->clkval_f << CLKVAL_F_OFFSET);
- writel(val, &fimd->vidcon0);
-
- val = (pd->vsync << VSYNC_PULSE_WIDTH_OFFSET) |
- (pd->lower_margin << V_FRONT_PORCH_OFFSET) |
- (pd->upper_margin << V_BACK_PORCH_OFFSET);
- writel(val, &disp_ctrl->vidtcon0);
-
- val = (pd->hsync << HSYNC_PULSE_WIDTH_OFFSET) |
- (pd->right_margin << H_FRONT_PORCH_OFFSET) |
- (pd->left_margin << H_BACK_PORCH_OFFSET);
- writel(val, &disp_ctrl->vidtcon1);
-
- val = ((pd->xres - 1) << HOZVAL_OFFSET) |
- ((pd->yres - 1) << LINEVAL_OFFSET);
- writel(val, &disp_ctrl->vidtcon2);
-
- writel((unsigned int)lcdbase, &fimd->vidw00add0b0);
- writel((unsigned int)lcdbase + fb_size, &fimd->vidw00add1b0);
-
- writel(pd->xres * 2, &fimd->vidw00add2);
-
- val = ((pd->xres - 1) << OSD_RIGHTBOTX_F_OFFSET);
- val |= ((pd->yres - 1) << OSD_RIGHTBOTY_F_OFFSET);
- writel(val, &fimd->vidosd0b);
- writel(pd->xres * pd->yres, &fimd->vidosd0c);
-
- setbits_le32(&fimd->shadowcon, CHANNEL0_EN);
-
- val = BPPMODE_F_RGB_16BIT_565 << BPPMODE_F_OFFSET;
- val |= ENWIN_F_ENABLE | HALF_WORD_SWAP_EN;
- writel(val, &fimd->wincon0);
-
- /* DPCLKCON_ENABLE */
- writel(1 << 1, &fimd->dpclkcon);
-}
-
-#ifdef UNUSED_CODE
-void exynos_fimd_disable(void)
-{
- struct exynos5_fimd *fimd = samsung_get_base_fimd();
-
- writel(0, &fimd->wincon0);
- clrbits_le32(&fimd->shadowcon, CHANNEL0_EN);
-}
-#endif
-
-/*
- * Configure DP in slave mode and wait for video stream.
- *
- * param dp pointer to main s5p-dp structure
- * param video_info pointer to main video_info structure.
- * return status
- */
-static int s5p_dp_config_video(struct s5p_dp_device *dp,
- struct video_info *video_info)
-{
- int timeout = 0;
- struct exynos5_dp *base = dp->base;
- struct mono_time start, current, end;
- s5p_dp_config_video_slave_mode(dp, video_info);
-
- s5p_dp_set_video_color_format(dp, video_info->color_depth,
- video_info->color_space,
- video_info->dynamic_range,
- video_info->ycbcr_coeff);
-
- if (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
- printk(BIOS_DEBUG, "PLL is not locked yet.\n");
- return -ERR_PLL_NOT_UNLOCKED;
- }
-
- timer_monotonic_get(&start);
- end = current = start;
- mono_time_add_usecs(&end, STREAM_ON_TIMEOUT * USECS_PER_MSEC);
- do {
- if (s5p_dp_is_slave_video_stream_clock_on(dp) == 0) {
- timeout++;
- break;
- }
- timer_monotonic_get(&current);
- } while (mono_time_before(&current, &end));
-
- if (!timeout) {
- printk(BIOS_ERR, "Video Clock Not ok after %ldus.\n",
- mono_time_diff_microseconds(&start, &end));
- return -ERR_VIDEO_CLOCK_BAD;
- }
-
- /* Set to use the register calculated M/N video */
- s5p_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
-
- clrbits_le32(&base->video_ctl_10, FORMAT_SEL);
-
- /* Disable video mute */
- clrbits_le32(&base->video_ctl_1, HDCP_VIDEO_MUTE);
-
- /* Configure video slave mode */
- s5p_dp_enable_video_master(dp);
-
- /* Enable video */
- setbits_le32(&base->video_ctl_1, VIDEO_EN);
- timeout = s5p_dp_is_video_stream_on(dp);
-
- if (timeout) {
- printk(BIOS_DEBUG, "Video Stream Not on\n");
- return -ERR_VIDEO_STREAM_BAD;
- }
-
- return 0;
-}
-
-/*
- * Set DP to enhanced mode. We use this for EVT1
- * param dp pointer to main s5p-dp structure
- * return status
- */
-static int s5p_dp_enable_rx_to_enhanced_mode(struct s5p_dp_device *dp)
-{
- u8 data;
-
- if (s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data)) {
- printk(BIOS_DEBUG, "DPCD read error\n");
- return -ERR_DPCD_READ_ERROR1;
- }
- if (s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
- DPCD_ENHANCED_FRAME_EN |
- (data & DPCD_LANE_COUNT_SET_MASK))) {
- printk(BIOS_DEBUG, "DPCD write error\n");
- return -ERR_DPCD_WRITE_ERROR1;
- }
-
- return 0;
-}
-
-/*
- * Enable scrambles mode. We use this for EVT1
- * param dp pointer to main s5p-dp structure
- * return status
- */
-static int s5p_dp_enable_scramble(struct s5p_dp_device *dp)
-{
- u8 data;
- struct exynos5_dp *base = dp->base;
-
- clrbits_le32(&base->dp_training_ptn_set, SCRAMBLING_DISABLE);
-
- if (s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET,
- &data)) {
- printk(BIOS_DEBUG, "DPCD read error\n");
- return -ERR_DPCD_READ_ERROR2;
- }
-
- if (s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET,
- (u8)(data & ~DPCD_SCRAMBLING_DISABLED))) {
- printk(BIOS_DEBUG, "DPCD write error\n");
- return -ERR_DPCD_WRITE_ERROR2;
- }
-
- return 0;
-}
-
-/*
- * Reset DP and prepare DP for init training
- * param dp pointer to main s5p-dp structure
- */
-static int s5p_dp_init_dp(struct s5p_dp_device *dp)
-{
- int ret, i;
- struct exynos5_dp *base = dp->base;
-
- for (i = 0; i < DP_INIT_TRIES; i++) {
- s5p_dp_reset(dp);
-
- /* SW defined function Normal operation */
- clrbits_le32(&base->func_en_1, SW_FUNC_EN_N);
-
- ret = s5p_dp_init_analog_func(dp);
- if (!ret)
- break;
-
- udelay(5000);
- printk(BIOS_DEBUG, "LCD retry init, attempt=%d ret=%d\n", i, ret);
- }
- if (i == DP_INIT_TRIES) {
- printk(BIOS_DEBUG, "LCD initialization failed, ret=%d\n", ret);
- return ret;
- }
-
- s5p_dp_init_aux(dp);
-
- return ret;
-}
-
-/*
- * Set pre-emphasis level
- * param dp pointer to main s5p-dp structure
- * param pre_emphasis pre-emphasis level
- * param lane lane number(0 - 3)
- * return status
- */
-static int s5p_dp_set_lane_lane_pre_emphasis(struct s5p_dp_device *dp,
- int pre_emphasis, int lane)
-{
- u32 reg;
- struct exynos5_dp *base = dp->base;
-
- reg = pre_emphasis << PRE_EMPHASIS_SET_SHIFT;
- switch (lane) {
- case 0:
- writel(reg, &base->ln0_link_trn_ctl);
- break;
- case 1:
- writel(reg, &base->ln1_link_trn_ctl);
- break;
-
- case 2:
- writel(reg, &base->ln2_link_trn_ctl);
- break;
-
- case 3:
- writel(reg, &base->ln3_link_trn_ctl);
- break;
- default:
- printk(BIOS_DEBUG, "%s: Invalid lane %d\n", __func__, lane);
- return -ERR_INVALID_LANE;
- }
- return 0;
-}
-
-/*
- * Read supported bandwidth type
- * param dp pointer to main s5p-dp structure
- * param bandwidth pointer to variable holding bandwidth type
- */
-static void s5p_dp_get_max_rx_bandwidth(struct s5p_dp_device *dp,
- u8 *bandwidth)
-{
- u8 data;
-
- /*
- * For DP rev.1.1, Maximum link rate of Main Link lanes
- * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
- */
- s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
- *bandwidth = data;
-}
-
-/*
- * Reset DP and prepare DP for init training
- * param dp pointer to main s5p-dp structure
- * param lane_count pointer to variable holding no of lanes
- */
-static void s5p_dp_get_max_rx_lane_count(struct s5p_dp_device *dp,
- u8 *lane_count)
-{
- u8 data;
-
- /*
- * For DP rev.1.1, Maximum number of Main Link lanes
- * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
- */
- s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
- *lane_count = data & DPCD_MAX_LANE_COUNT_MASK;
-}
-
-/*
- * DP H/w Link Training. Set DPCD link rate and bandwidth.
- * param dp pointer to main s5p-dp structure
- * param max_lane No of lanes
- * param max_rate bandwidth
- * return status
- */
-static int s5p_dp_hw_link_training(struct s5p_dp_device *dp,
- unsigned int max_lane,
- unsigned int max_rate)
-{
- int pll_is_locked = 0;
- u32 data;
- int lane;
- struct mono_time current, end;
- struct exynos5_dp *base = dp->base;
-
- /* Stop Video */
- clrbits_le32(&base->video_ctl_1, VIDEO_EN);
-
- timer_monotonic_get(&current);
- end = current;
- mono_time_add_msecs(&end, PLL_LOCK_TIMEOUT);
-
- while ((pll_is_locked = s5p_dp_get_pll_lock_status(dp)) == PLL_UNLOCKED) {
- if (mono_time_after(&current, &end)) {
- /* Ignore this error, and try to continue */
- printk(BIOS_ERR, "PLL is not locked yet.\n");
- break;
- }
- timer_monotonic_get(&current);
- }
- printk(BIOS_SPEW, "PLL is %slocked\n",
- pll_is_locked == PLL_LOCKED ? "": "not ");
- /* Reset Macro */
- setbits_le32(&base->dp_phy_test, MACRO_RST);
-
- /* 10 us is the minimum reset time. */
- udelay(10);
-
- clrbits_le32(&base->dp_phy_test, MACRO_RST);
-
- /* Set TX pre-emphasis to minimum */
- for (lane = 0; lane < max_lane; lane++)
- if (s5p_dp_set_lane_lane_pre_emphasis(dp,
- PRE_EMPHASIS_LEVEL_0, lane)) {
- printk(BIOS_DEBUG, "Unable to set pre emphasis level\n");
- return -ERR_PRE_EMPHASIS_LEVELS;
- }
-
- /* All DP analog module power up */
- writel(0x00, &base->dp_phy_pd);
-
- /* Initialize by reading RX's DPCD */
- s5p_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
- s5p_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
-
- printk(BIOS_SPEW, "%s: rate 0x%x, lane_count %d\n", __func__,
- dp->link_train.link_rate, dp->link_train.lane_count);
-
- if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
- (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
- printk(BIOS_DEBUG, "Rx Max Link Rate is abnormal :%x !\n",
- dp->link_train.link_rate);
- /* Not Retrying */
- return -ERR_LINK_RATE_ABNORMAL;
- }
-
- if (dp->link_train.lane_count == 0) {
- printk(BIOS_DEBUG, "Rx Max Lane count is abnormal :%x !\n",
- dp->link_train.lane_count);
- /* Not retrying */
- return -ERR_MAX_LANE_COUNT_ABNORMAL;
- }
-
- /* Setup TX lane count & rate */
- if (dp->link_train.lane_count > max_lane)
- dp->link_train.lane_count = max_lane;
- if (dp->link_train.link_rate > max_rate)
- dp->link_train.link_rate = max_rate;
-
- /* Set link rate and count as you want to establish*/
- writel(dp->link_train.lane_count, &base->lane_count_set);
- writel(dp->link_train.link_rate, &base->link_bw_set);
-
- /* Set sink to D0 (Sink Not Ready) mode. */
- s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
- DPCD_SET_POWER_STATE_D0);
-
- /* Start HW link training */
- writel(HW_TRAINING_EN, &base->dp_hw_link_training);
-
- /* Wait until HW link training done */
- s5p_dp_wait_hw_link_training_done(dp);
-
- /* Get hardware link training status */
- data = readl(&base->dp_hw_link_training);
- printk(BIOS_SPEW, "hardware link training status: 0x%08x\n", data);
- if (data != 0) {
- printk(BIOS_ERR, " H/W link training failure: 0x%x\n", data);
- return -ERR_LINK_TRAINING_FAILURE;
- }
-
- /* Get Link Bandwidth */
- data = readl(&base->link_bw_set);
-
- dp->link_train.link_rate = data;
-
- data = readl(&base->lane_count_set);
- dp->link_train.lane_count = data;
- printk(BIOS_SPEW, "Done training: Link bandwidth: 0x%x, lane_count: %d\n",
- dp->link_train.link_rate, data);
-
- return 0;
-}
-
-/*
- * Initialize DP display
- */
-int dp_controller_init(struct s5p_dp_device *dp_device)
-{
- int ret;
- struct s5p_dp_device *dp = dp_device;
- struct exynos5_dp *base;
-
- clock_init_dp_clock();
-
- power_enable_dp_phy();
- ret = s5p_dp_init_dp(dp);
- if (ret) {
- printk(BIOS_ERR, "%s: Could not initialize dp\n", __func__);
- return ret;
- }
-
- ret = s5p_dp_hw_link_training(dp, dp->video_info->lane_count,
- dp->video_info->link_rate);
- if (ret) {
- printk(BIOS_ERR, "unable to do link train\n");
- return ret;
- }
- /* Minimum delay after H/w Link training */
- udelay(1000);
-
- ret = s5p_dp_enable_scramble(dp);
- if (ret) {
- printk(BIOS_ERR, "unable to set scramble mode\n");
- return ret;
- }
-
- ret = s5p_dp_enable_rx_to_enhanced_mode(dp);
- if (ret) {
- printk(BIOS_ERR, "unable to set enhanced mode\n");
- return ret;
- }
-
-
- base = dp->base;
- /* Enable enhanced mode */
- setbits_le32(&base->sys_ctl_4, ENHANCED);
-
- writel(dp->link_train.lane_count, &base->lane_count_set);
- writel(dp->link_train.link_rate, &base->link_bw_set);
-
- s5p_dp_init_video(dp);
- ret = s5p_dp_config_video(dp, dp->video_info);
- if (ret) {
- printk(BIOS_ERR, "unable to config video\n");
- return ret;
- }
-
- return 0;
-}
-
-/**
- * Init the LCD controller
- *
- * @param lcdbase Base address of LCD frame buffer
- * @return 0 if ok, -ve error code on error
- */
-int lcd_ctrl_init(unsigned long int fb_size,
- struct exynos5_fimd_panel *panel_data, void *lcdbase)
-{
- int ret = 0;
-
- fimd_bypass();
- fb_init(fb_size, lcdbase, panel_data);
- return ret;
-}
diff --git a/src/cpu/samsung/exynos5420/fimd.c b/src/cpu/samsung/exynos5420/fimd.c
new file mode 100644
index 0000000000..b94148a6b1
--- /dev/null
+++ b/src/cpu/samsung/exynos5420/fimd.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright 2013 Google Inc.
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * Author: InKi Dae <inki.dae@samsung.com>
+ * Author: Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <delay.h>
+#include "timer.h"
+#include "clk.h"
+#include "cpu.h"
+#include "periph.h"
+#include "dp.h"
+#include "fimd.h"
+#include "sysreg.h"
+
+/* left here because it's a counterexample of good style. u-boot
+ * likes to call a function to get a base address. To get that they
+ * walk the device tree several times. It's costly. So they turn a
+ * known-at-build-time constant into a bunch of function calls. What
+ * to do about this inefficiency? Fix the inefficiency? No, scarf
+ * variables away in global memory of course, and remove all hope of
+ * optimization. Bad idea.
+ *
+ * the u-boot sources that define fimd base are ... bizarre. I'm going
+ * with a hardcoded hack until we get this working. FIXME.
+ *
+ * static struct exynos_fb *fimd_ctrl * =
+ * (void *)0x14400000; //samsung_get_base_fimd();
+ */
+
+/* fairly useful debugging stuff. */
+#if 0
+static inline void fwadl(unsigned long l,void *v) {
+ writel(l, v);
+ printk(BIOS_SPEW, "W %p %p\n", v, (void *)l);
+}
+#define lwritel(a,b) fwadl((unsigned long)(a), (void *)(b))
+
+static inline unsigned long fradl(void *v) {
+ unsigned long l = readl(v);
+ printk(BIOS_SPEW, "R %p %p\n", v, (void *)l);
+ return l;
+}
+
+#define lreadl(a) fradl((void *)(a))
+
+#else
+#define lwritel(a,b) writel((unsigned long)(a), (void *)(b))
+#define lreadl(a) readl((void *)(a))
+#endif
+
+/* not sure where we want this so ... */
+static unsigned long get_lcd_clk(void)
+{
+ struct exynos5420_clock *clk = samsung_get_base_clock();
+ u32 pclk, sclk;
+ unsigned int sel;
+ unsigned int ratio;
+
+ /*
+ * CLK_SRC_DISP10
+ * CLKMUX_FIMD1 [4]
+ * 0: SCLK_RPLL
+ * 1: SCLK_SPLL
+ */
+ sel = lreadl(&clk->clk_src_disp10);
+ sel &= (1 << 4);
+
+ if (sel){
+ sclk = get_pll_clk(SPLL);
+ } else {
+ sclk = get_pll_clk(RPLL);
+ }
+
+ /*
+ * CLK_DIV_DISP10
+ * FIMD1_RATIO [3:0]
+ */
+ ratio = lreadl(&clk->clk_div_disp10);
+ ratio = ratio & 0xf;
+
+ pclk = sclk / (ratio + 1);
+
+ return pclk;
+}
+
+static void exynos_fimd_set_dualrgb(vidinfo_t *vid, unsigned int enabled)
+{
+ unsigned int cfg = 0;
+ printk(BIOS_SPEW, "%s %s\n", __func__, enabled ? "enabled" : "not enabled");
+ if (enabled) {
+ cfg = EXYNOS_DUALRGB_BYPASS_DUAL | EXYNOS_DUALRGB_LINESPLIT |
+ EXYNOS_DUALRGB_VDEN_EN_ENABLE;
+
+ /* in case of Line Split mode, MAIN_CNT doesn't neet to set. */
+ cfg |= EXYNOS_DUALRGB_SUB_CNT(vid->vl_col / 2) |
+ EXYNOS_DUALRGB_MAIN_CNT(0);
+ }
+
+ lwritel(cfg, &FIMD_CTRL->dualrgb);
+}
+
+static void exynos_fimd_set_dp_clkcon(unsigned int enabled)
+{
+ unsigned int cfg = 0;
+
+ if (enabled){
+ cfg = EXYNOS_DP_CLK_ENABLE;
+ }
+
+ lwritel(cfg, &FIMD_CTRL->dp_mie_clkcon);
+}
+
+static void exynos_fimd_set_par(vidinfo_t *vid, unsigned int win_id)
+{
+ unsigned int cfg = 0;
+ printk(BIOS_SPEW, "%s %d\n", __func__, win_id);
+ /* set window control */
+ cfg = lreadl(&FIMD_CTRL->wincon0 +
+ EXYNOS_WINCON(win_id));
+
+ cfg &= ~(EXYNOS_WINCON_BITSWP_ENABLE | EXYNOS_WINCON_BYTESWP_ENABLE |
+ EXYNOS_WINCON_HAWSWP_ENABLE | EXYNOS_WINCON_WSWP_ENABLE |
+ EXYNOS_WINCON_BURSTLEN_MASK | EXYNOS_WINCON_BPPMODE_MASK |
+ EXYNOS_WINCON_INRGB_MASK | EXYNOS_WINCON_DATAPATH_MASK);
+
+ /* DATAPATH is DMA */
+ cfg |= EXYNOS_WINCON_DATAPATH_DMA;
+
+ cfg |= EXYNOS_WINCON_HAWSWP_ENABLE;
+
+ /* dma burst is 16 */
+ cfg |= EXYNOS_WINCON_BURSTLEN_16WORD;
+
+ cfg |= EXYNOS_WINCON_BPPMODE_16BPP_565;
+
+ lwritel(cfg, &FIMD_CTRL->wincon0 +
+ EXYNOS_WINCON(win_id));
+
+ /* set window position to x=0, y=0*/
+ cfg = EXYNOS_VIDOSD_LEFT_X(0) | EXYNOS_VIDOSD_TOP_Y(0);
+ lwritel(cfg, &FIMD_CTRL->vidosd0a +
+ EXYNOS_VIDOSD(win_id));
+
+ cfg = EXYNOS_VIDOSD_RIGHT_X(vid->vl_col - 1) |
+ EXYNOS_VIDOSD_BOTTOM_Y(vid->vl_row - 1) |
+ EXYNOS_VIDOSD_RIGHT_X_E(1) |
+ EXYNOS_VIDOSD_BOTTOM_Y_E(0);
+
+ lwritel(cfg, &FIMD_CTRL->vidosd0b +
+ EXYNOS_VIDOSD(win_id));
+ /* set window size for window0*/
+ cfg = EXYNOS_VIDOSD_SIZE(vid->vl_col * vid->vl_row);
+ lwritel(cfg, &FIMD_CTRL->vidosd0c +
+ EXYNOS_VIDOSD(win_id));
+}
+
+static void exynos_fimd_set_buffer_address(vidinfo_t *vid,
+ void *screen_base, int win_id)
+{
+ u32 start_addr, end_addr;
+ printk(BIOS_SPEW, "%s %d\n", __func__, win_id);
+ start_addr = (u32)screen_base;
+ end_addr = start_addr + ((vid->vl_col * ((1<<vid->vl_bpix) / 8)) *
+ vid->vl_row);
+
+ lwritel(start_addr, &FIMD_CTRL->vidw00add0b0 +
+ EXYNOS_BUFFER_OFFSET(win_id));
+ lwritel(end_addr, &FIMD_CTRL->vidw00add1b0 +
+ EXYNOS_BUFFER_OFFSET(win_id));
+}
+
+static void exynos_fimd_set_clock(vidinfo_t *vid)
+{
+ unsigned int cfg = 0, div = 0, remainder = 0, remainder_div;
+ unsigned long pixel_clock;
+ unsigned long long src_clock;
+ printk(BIOS_SPEW, "%s\n", __func__);
+ if (vid->dual_lcd_enabled) {
+ pixel_clock = vid->vl_freq *
+ (vid->vl_hspw + vid->vl_hfpd +
+ vid->vl_hbpd + vid->vl_col / 2) *
+ (vid->vl_vspw + vid->vl_vfpd +
+ vid->vl_vbpd + vid->vl_row);
+ } else if (vid->interface_mode == FIMD_CPU_INTERFACE) {
+ pixel_clock = vid->vl_freq *
+ vid->vl_width * vid->vl_height *
+ (vid->cs_setup + vid->wr_setup +
+ vid->wr_act + vid->wr_hold + 1);
+ } else {
+ pixel_clock = vid->vl_freq *
+ (vid->vl_hspw + vid->vl_hfpd +
+ vid->vl_hbpd + vid->vl_col) *
+ (vid->vl_vspw + vid->vl_vfpd +
+ vid->vl_vbpd + vid->vl_row);
+ }
+ printk(BIOS_SPEW, "Pixel clock is %lx\n", pixel_clock);
+
+ cfg = lreadl(&FIMD_CTRL->vidcon0);
+ cfg &= ~(EXYNOS_VIDCON0_CLKSEL_MASK | EXYNOS_VIDCON0_CLKVALUP_MASK |
+ EXYNOS_VIDCON0_CLKVAL_F(0xFF) | EXYNOS_VIDCON0_VCLKEN_MASK |
+ EXYNOS_VIDCON0_CLKDIR_MASK);
+ cfg |= (EXYNOS_VIDCON0_CLKSEL_SCLK | EXYNOS_VIDCON0_CLKVALUP_ALWAYS |
+ EXYNOS_VIDCON0_VCLKEN_NORMAL | EXYNOS_VIDCON0_CLKDIR_DIVIDED);
+
+ src_clock = (unsigned long long) get_lcd_clk();
+
+ /* get quotient and remainder. */
+ remainder = src_clock % pixel_clock;
+ src_clock /= pixel_clock;
+
+ div = src_clock;
+
+ remainder *= 10;
+ remainder_div = remainder / pixel_clock;
+
+ /* round about one places of decimals. */
+ if (remainder_div >= 5)
+ div++;
+
+ /* in case of dual lcd mode. */
+ if (vid->dual_lcd_enabled)
+ div--;
+
+ cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1);
+ lwritel(cfg, &FIMD_CTRL->vidcon0);
+}
+
+void exynos_set_trigger(void)
+{
+ unsigned int cfg = 0;
+ printk(BIOS_SPEW, "%s\n", __func__);
+ cfg = lreadl(&FIMD_CTRL->trigcon);
+
+ cfg |= (EXYNOS_I80SOFT_TRIG_EN | EXYNOS_I80START_TRIG);
+
+ lwritel(cfg, &FIMD_CTRL->trigcon);
+}
+
+int exynos_is_i80_frame_done(void)
+{
+ unsigned int cfg = 0;
+ int status;
+ printk(BIOS_SPEW, "%s\n", __func__);
+ cfg = lreadl(&FIMD_CTRL->trigcon);
+
+ /* frame done func is valid only when TRIMODE[0] is set to 1. */
+ status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) ==
+ EXYNOS_I80STATUS_TRIG_DONE;
+
+ return status;
+}
+
+static void exynos_fimd_lcd_on(void)
+{
+ unsigned int cfg = 0;
+
+ printk(BIOS_SPEW, "%s\n", __func__);
+ /* display on */
+ cfg = lreadl(&FIMD_CTRL->vidcon0);
+ cfg |= (EXYNOS_VIDCON0_ENVID_ENABLE | EXYNOS_VIDCON0_ENVID_F_ENABLE);
+ lwritel(cfg, &FIMD_CTRL->vidcon0);
+}
+
+static void exynos_fimd_window_on(unsigned int win_id)
+{
+ unsigned int cfg = 0;
+ printk(BIOS_SPEW, "%s %d\n", __func__, win_id);
+ /* enable window */
+ cfg = lreadl(&FIMD_CTRL->wincon0 +
+ EXYNOS_WINCON(win_id));
+ cfg |= EXYNOS_WINCON_ENWIN_ENABLE;
+ lwritel(cfg, &FIMD_CTRL->wincon0 +
+ EXYNOS_WINCON(win_id));
+
+ cfg = lreadl(&FIMD_CTRL->winshmap);
+ cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id);
+ lwritel(cfg, &FIMD_CTRL->winshmap);
+ cfg = lreadl(&FIMD_CTRL->winshmap);
+}
+
+void exynos_fimd_lcd_off(void)
+{
+ unsigned int cfg = 0;
+ printk(BIOS_SPEW, "%s\n", __func__);
+
+ cfg = lreadl(&FIMD_CTRL->vidcon0);
+ cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE);
+ lwritel(cfg, &FIMD_CTRL->vidcon0);
+}
+
+void exynos_fimd_window_off(unsigned int win_id)
+{
+ unsigned int cfg = 0;
+ printk(BIOS_SPEW, "%s %d\n", __func__, win_id);
+
+ cfg = lreadl(&FIMD_CTRL->wincon0 +
+ EXYNOS_WINCON(win_id));
+ cfg &= EXYNOS_WINCON_ENWIN_DISABLE;
+ lwritel(cfg, &FIMD_CTRL->wincon0 +
+ EXYNOS_WINCON(win_id));
+
+ cfg = lreadl(&FIMD_CTRL->winshmap);
+ cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id);
+ lwritel(cfg, &FIMD_CTRL->winshmap);
+}
+
+static void exynos5_set_system_display(void)
+{
+ struct exynos5_sysreg *sysreg = samsung_get_base_sysreg();
+ unsigned int cfg = 0;
+
+ /*
+ * system register path set
+ * 0: MIE/MDNIE
+ * 1: FIMD Bypass
+ */
+ cfg = lreadl(&sysreg->disp1blk_cfg);
+ cfg |= (1 << 15);
+ lwritel(cfg, &sysreg->disp1blk_cfg);
+}
+
+void exynos_fimd_lcd_init(vidinfo_t *vid)
+{
+ unsigned int cfg = 0, rgb_mode;
+ unsigned int offset;
+
+ offset = exynos_fimd_get_base_offset();
+ printk(BIOS_SPEW, "%s\n", __func__);
+ exynos5_set_system_display();
+
+ rgb_mode = vid->rgb_mode;
+
+ if (vid->interface_mode == FIMD_RGB_INTERFACE) {
+ printk(BIOS_SPEW, "%s FIMD_RGB_INTERFACE\n", __func__);
+
+ cfg |= EXYNOS_VIDCON0_VIDOUT_RGB;
+ lwritel(cfg, &FIMD_CTRL->vidcon0);
+
+ cfg = lreadl(&FIMD_CTRL->vidcon2);
+ cfg &= ~(EXYNOS_VIDCON2_WB_MASK |
+ EXYNOS_VIDCON2_TVFORMATSEL_MASK |
+ EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK);
+ cfg |= EXYNOS_VIDCON2_WB_DISABLE;
+ lwritel(cfg, &FIMD_CTRL->vidcon2);
+
+ /* set polarity */
+ cfg = 0;
+ if (!vid->vl_clkp)
+ cfg |= EXYNOS_VIDCON1_IVCLK_RISING_EDGE;
+ if (!vid->vl_hsp)
+ cfg |= EXYNOS_VIDCON1_IHSYNC_INVERT;
+ if (!vid->vl_vsp)
+ cfg |= EXYNOS_VIDCON1_IVSYNC_INVERT;
+ if (!vid->vl_dp)
+ cfg |= EXYNOS_VIDCON1_IVDEN_INVERT;
+
+ lwritel(cfg, &FIMD_CTRL->vidcon1 + offset);
+
+ /* set timing */
+ cfg = EXYNOS_VIDTCON0_VFPD(vid->vl_vfpd - 1);
+ cfg |= EXYNOS_VIDTCON0_VBPD(vid->vl_vbpd - 1);
+ cfg |= EXYNOS_VIDTCON0_VSPW(vid->vl_vspw - 1);
+ lwritel(cfg, &FIMD_CTRL->vidtcon0 + offset);
+
+ cfg = EXYNOS_VIDTCON1_HFPD(vid->vl_hfpd - 1);
+ cfg |= EXYNOS_VIDTCON1_HBPD(vid->vl_hbpd - 1);
+ cfg |= EXYNOS_VIDTCON1_HSPW(vid->vl_hspw - 1);
+
+ lwritel(cfg, &FIMD_CTRL->vidtcon1 + offset);
+
+ /* set lcd size */
+ cfg = EXYNOS_VIDTCON2_HOZVAL(vid->vl_col - 1) |
+ EXYNOS_VIDTCON2_LINEVAL(vid->vl_row - 1) |
+ EXYNOS_VIDTCON2_HOZVAL_E(vid->vl_col - 1) |
+ EXYNOS_VIDTCON2_LINEVAL_E(vid->vl_row - 1);
+
+ lwritel(cfg, &FIMD_CTRL->vidtcon2 + offset);
+ }
+
+ /* set display mode */
+ cfg = lreadl(&FIMD_CTRL->vidcon0);
+ cfg &= ~EXYNOS_VIDCON0_PNRMODE_MASK;
+ cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT);
+ lwritel(cfg, &FIMD_CTRL->vidcon0);
+
+ /* set par */
+ exynos_fimd_set_par(vid, vid->win_id);
+
+ /* set memory address */
+ exynos_fimd_set_buffer_address(vid, vid->screen_base, vid->win_id);
+
+ /* set buffer size */
+ cfg = EXYNOS_VIDADDR_PAGEWIDTH(vid->vl_col * (1<<vid->vl_bpix) / 8) |
+ EXYNOS_VIDADDR_PAGEWIDTH_E(vid->vl_col * (1<<vid->vl_bpix) / 8) |
+ EXYNOS_VIDADDR_OFFSIZE(0) |
+ EXYNOS_VIDADDR_OFFSIZE_E(0);
+
+ lwritel(cfg, &FIMD_CTRL->vidw00add2 +
+ EXYNOS_BUFFER_SIZE(vid->win_id));
+
+ /* set clock */
+ exynos_fimd_set_clock(vid);
+
+ /* set rgb mode to dual lcd. */
+ exynos_fimd_set_dualrgb(vid, vid->dual_lcd_enabled);
+
+ /* display on */
+ exynos_fimd_lcd_on();
+
+ /* window on */
+ exynos_fimd_window_on(vid->win_id);
+
+ exynos_fimd_set_dp_clkcon(vid->dp_enabled);
+ exynos5_set_system_display();
+ printk(BIOS_SPEW, "%s: done\n", __func__);
+}
+
+unsigned long exynos_fimd_calc_fbsize(vidinfo_t *vid)
+{
+ printk(BIOS_SPEW, "%s\n", __func__);
+ return vid->vl_col * vid->vl_row * ((1<<vid->vl_bpix) / 8);
+}
+
+void exynos_fimd_lcd_disable(void)
+{
+ int i;
+ printk(BIOS_SPEW, "%s\n", __func__);
+
+ for (i = 0; i < 4; i++)
+ exynos_fimd_window_off(i);
+}
diff --git a/src/cpu/samsung/exynos5420/fimd.h b/src/cpu/samsung/exynos5420/fimd.h
index 661ed9ec6f..7d6897958b 100644
--- a/src/cpu/samsung/exynos5420/fimd.h
+++ b/src/cpu/samsung/exynos5420/fimd.h
@@ -25,39 +25,39 @@
/* FIMD register map */
struct exynos5_fimd {
/* This is an incomplete list. Add registers as and when required */
- unsigned int vidcon0;
- unsigned char res1[0x1c];
- unsigned int wincon0;
- unsigned int wincon1;
- unsigned int wincon2;
- unsigned int wincon3;
- unsigned int wincon4;
- unsigned int shadowcon;
- unsigned char res2[0x8];
- unsigned int vidosd0a;
- unsigned int vidosd0b;
- unsigned int vidosd0c;
- unsigned char res3[0x54];
- unsigned int vidw00add0b0;
- unsigned char res4[0x2c];
- unsigned int vidw00add1b0;
- unsigned char res5[0x2c];
- unsigned int vidw00add2;
- unsigned char res6[0x3c];
- unsigned int w1keycon0;
- unsigned int w1keycon1;
- unsigned int w2keycon0;
- unsigned int w2keycon1;
- unsigned int w3keycon0;
- unsigned int w3keycon1;
- unsigned int w4keycon0;
- unsigned int w4keycon1;
- unsigned char res7[0x20];
- unsigned int win0map;
- unsigned char res8[0xdc];
- unsigned int blendcon;
- unsigned char res9[0x18];
- unsigned int dpclkcon;
+ u32 vidcon0;
+ u8 res1[0x1c];
+ u32 wincon0;
+ u32 wincon1;
+ u32 wincon2;
+ u32 wincon3;
+ u32 wincon4;
+ u32 shadowcon;
+ u8 res2[0x8];
+ u32 vidosd0a;
+ u32 vidosd0b;
+ u32 vidosd0c;
+ u8 res3[0x54];
+ u32 vidw00add0b0;
+ u8 res4[0x2c];
+ u32 vidw00add1b0;
+ u8 res5[0x2c];
+ u32 vidw00add2;
+ u8 res6[0x3c];
+ u32 w1keycon0;
+ u32 w1keycon1;
+ u32 w2keycon0;
+ u32 w2keycon1;
+ u32 w3keycon0;
+ u32 w3keycon1;
+ u32 w4keycon0;
+ u32 w4keycon1;
+ u8 res7[0x20];
+ u32 win0map;
+ u8 res8[0xdc];
+ u32 blendcon;
+ u8 res9[0x18];
+ u32 dpclkcon;
};
#define W0_SHADOW_PROTECT (0x1 << 10)
@@ -86,7 +86,7 @@ struct exynos5_fimd_panel {
unsigned int upper_margin; /* Vertical Backporch */
unsigned int lower_margin; /* Vertical frontporch */
unsigned int vsync; /* Vertical Sync Pulse Width */
- unsigned int left_margin; /* Horizantal Backporch */
+ unsigned int left_margin; /* Horizontal Backporch */
unsigned int right_margin; /* Horizontal Frontporch */
unsigned int hsync; /* Horizontal Sync Pulse Width */
unsigned int xres; /* X Resolution */
@@ -95,15 +95,15 @@ struct exynos5_fimd_panel {
/* LCDIF Register Map */
struct exynos5_disp_ctrl {
- unsigned int vidout_con;
- unsigned int vidcon1;
- unsigned char res1[0x8];
- unsigned int vidtcon0;
- unsigned int vidtcon1;
- unsigned int vidtcon2;
- unsigned int vidtcon3;
- unsigned char res2[0x184];
- unsigned int trigcon;
+ u32 vidout_con;
+ u32 vidcon1;
+ u8 res1[0x8];
+ u32 vidtcon0;
+ u32 vidtcon1;
+ u32 vidtcon2;
+ u32 vidtcon3;
+ u8 res2[0x184];
+ u32 trigcon;
};
#define VCLK_RISING_EDGE (1 << 7)
@@ -135,4 +135,79 @@ struct exynos5_disp_ctrl {
#define OSD_RIGHTBOTX_F_OFFSET 11
#define OSD_RIGHTBOTY_F_OFFSET 0
+
+#define FIMD_CTRL ((struct exynos_fb *)0x14400000)
+
+/* from u-boot fb.h. It needs to be merged with these dp structs maybe. */
+enum {
+ FIMD_RGB_INTERFACE = 1,
+ FIMD_CPU_INTERFACE = 2,
+};
+
+enum exynos_fb_rgb_mode_t {
+ MODE_RGB_P = 0,
+ MODE_BGR_P = 1,
+ MODE_RGB_S = 2,
+ MODE_BGR_S = 3,
+};
+
+typedef struct vidinfo {
+ u16 vl_col; /* Number of columns (i.e. 640) */
+ u16 vl_row; /* Number of rows (i.e. 480) */
+ u16 vl_width; /* Width of display area in millimeters */
+ u16 vl_height; /* Height of display area in millimeters */
+
+ /* LCD configuration register */
+ u8 vl_freq; /* Frequency */
+ u8 vl_clkp; /* Clock polarity */
+ u8 vl_oep; /* Output Enable polarity */
+ u8 vl_hsp; /* Horizontal Sync polarity */
+ u8 vl_vsp; /* Vertical Sync polarity */
+ u8 vl_dp; /* Data polarity */
+ u8 vl_bpix; /* Bits per pixel */
+
+ /* Horizontal control register. Timing from data sheet */
+ u8 vl_hspw; /* Horz sync pulse width */
+ u8 vl_hfpd; /* Wait before of line */
+ u8 vl_hbpd; /* Wait end of line */
+
+ /* Vertical control register. */
+ u8 vl_vspw; /* Vertical sync pulse width */
+ u8 vl_vfpd; /* Wait before of frame */
+ u8 vl_vbpd; /* Wait end of frame */
+ u8 vl_cmd_allow_len; /* Wait end of frame */
+
+ unsigned int win_id;
+ unsigned int init_delay;
+ unsigned int power_on_delay;
+ unsigned int reset_delay;
+ unsigned int interface_mode;
+ unsigned int mipi_enabled;
+ unsigned int dp_enabled;
+ unsigned int cs_setup;
+ unsigned int wr_setup;
+ unsigned int wr_act;
+ unsigned int wr_hold;
+ unsigned int rgb_mode;
+ unsigned int resolution;
+
+ /* parent clock name(MPLL, EPLL or VPLL) */
+ unsigned int pclk_name;
+ /* ratio value for source clock from parent clock. */
+ unsigned int sclk_div;
+
+ unsigned int dual_lcd_enabled;
+ void *screen_base;
+ void *cmap; /* Points at 8 to 16 bit conversion map. */
+} vidinfo_t;
+
+/* fimd.c */
+void exynos_set_trigger(void);
+int exynos_is_i80_frame_done(void);
+void exynos_fimd_lcd_off(void);
+void exynos_fimd_window_off(unsigned int win_id);
+unsigned long exynos_fimd_calc_fbsize(vidinfo_t *vid);
+void exynos_fimd_lcd_disable(void);
+void exynos_fimd_lcd_init(vidinfo_t *vid);
+
#endif
diff --git a/src/cpu/samsung/exynos5420/power.c b/src/cpu/samsung/exynos5420/power.c
index 18e0299eca..3215462e36 100644
--- a/src/cpu/samsung/exynos5420/power.c
+++ b/src/cpu/samsung/exynos5420/power.c
@@ -64,7 +64,7 @@ void power_enable_dp_phy(void)
struct exynos5_power *power =
samsung_get_base_power();
- setbits_le32(&power->dptx_phy_control, DPTX_PHY_ENABLE);
+ setbits_le32(&power->dptx_phy_control, EXYNOS_DP_PHY_ENABLE);
}
void power_enable_usb_phy(void)
diff --git a/src/cpu/samsung/exynos5420/power.h b/src/cpu/samsung/exynos5420/power.h
index 3c019d6dc5..665e94c197 100644
--- a/src/cpu/samsung/exynos5420/power.h
+++ b/src/cpu/samsung/exynos5420/power.h
@@ -32,7 +32,7 @@ void power_enable_hw_thermal_trip(void);
#define POWER_PS_HOLD_CONTROL_DATA_HIGH (1 << 8)
#define POWER_ENABLE_HW_TRIP (1UL << 31)
-#define DPTX_PHY_ENABLE (1 << 0)
+#define EXYNOS_DP_PHY_ENABLE (1 << 0)
/* PMU_DEBUG bits [12:8] = 0x1000 selects XXTI clock source */
#define PMU_DEBUG_XXTI 0x1000
diff --git a/src/lib/edid.c b/src/lib/edid.c
index b2bd9b716a..4be0dc6652 100644
--- a/src/lib/edid.c
+++ b/src/lib/edid.c
@@ -1448,12 +1448,12 @@ void set_vbe_mode_info_valid(struct edid *edid, uintptr_t fb_addr)
break;
case 16:
/* packed into 2-byte words */
- edid_fb.red_mask_pos = 12;
- edid_fb.red_mask_size = 4;
- edid_fb.green_mask_pos = 8;
- edid_fb.green_mask_size = 4;
+ edid_fb.red_mask_pos = 11;
+ edid_fb.red_mask_size = 5;
+ edid_fb.green_mask_pos = 5;
+ edid_fb.green_mask_size = 6;
edid_fb.blue_mask_pos = 0;
- edid_fb.blue_mask_size = 4;
+ edid_fb.blue_mask_size = 5;
break;
default:
printk(BIOS_SPEW, "%s: unsupported BPP %d\n", __func__,
diff --git a/src/mainboard/google/pit/mainboard.c b/src/mainboard/google/pit/mainboard.c
index 5c67df206d..f25c2a55b2 100644
--- a/src/mainboard/google/pit/mainboard.c
+++ b/src/mainboard/google/pit/mainboard.c
@@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <string.h>
#include <console/console.h>
#include <device/device.h>
#include <device/i2c.h>
@@ -33,7 +34,8 @@
#include <cpu/samsung/exynos5420/gpio.h>
#include <cpu/samsung/exynos5420/power.h>
#include <cpu/samsung/exynos5420/i2c.h>
-#include <cpu/samsung/exynos5420/dp-core.h>
+#include <cpu/samsung/exynos5420/dp.h>
+#include <cpu/samsung/exynos5420/fimd.h>
#include <drivers/parade/ps8625/ps8625.h>
#include <ec/google/chromeec/ec.h>
#include <stdlib.h>
@@ -52,6 +54,64 @@ static struct edid edid = {
.bytes_per_line = 2 * 1366
};
+/* from the fdt */
+static struct vidinfo vidinfo = {
+ .vl_freq = 60,
+ .vl_col = 1366,
+ .vl_row = 768,
+ .vl_width = 1366,
+ .vl_height = 768,
+ .vl_clkp = 1,
+ .vl_dp = 1,
+ .vl_bpix = 4,
+ .vl_hspw = 32,
+ .vl_hbpd = 40,
+ .vl_hfpd = 40,
+ .vl_vspw = 6,
+ .vl_vbpd = 10,
+ .vl_vfpd = 12,
+ .vl_cmd_allow_len = 0xf,
+ .win_id = 3,
+ .dp_enabled = 1,
+ .dual_lcd_enabled = 0,
+ .interface_mode = FIMD_RGB_INTERFACE,
+};
+
+static unsigned char panel_edid[] = {
+ 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x06,0xaf,0x5c,0x31,0x00,0x00,0x00,0x00,
+ 0x00,0x16,0x01,0x03,0x80,0x1a,0x0e,0x78,
+ 0x0a,0x99,0x85,0x95,0x55,0x56,0x92,0x28,
+ 0x22,0x50,0x54,0x00,0x00,0x00,0x01,0x01,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0xa3,0x1b,
+ 0x56,0x7e,0x50,0x00,0x16,0x30,0x30,0x20,
+ 0x36,0x00,0x00,0x90,0x10,0x00,0x00,0x18,
+ 0x6d,0x12,0x56,0x7e,0x50,0x00,0x16,0x30,
+ 0x30,0x20,0x36,0x00,0x00,0x90,0x10,0x00,
+ 0x00,0x18,0x00,0x00,0x00,0xfe,0x00,0x41,
+ 0x55,0x4f,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x00,0x00,0x00,0xfe,
+ 0x00,0x42,0x31,0x31,0x36,0x58,0x57,0x30,
+ 0x33,0x20,0x56,0x31,0x20,0x0a,0x00,0x3d,
+ 0x00,0xc0,0x00,0x00,0x27,0xfd,0x00,0x20,
+ 0x02,0x59,0x07,0x00,0x64,0x3e,0x07,0x02,
+ 0x00,0x00,0xcd,0x12,0x59,0xff,0x10,0x03,
+ 0x00,0x00,0x00,0x00,0x64,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,
+ 0x9c,0x3f,0x07,0x02,0x31,0xf9,0x00,0x20,
+ 0x59,0xff,0x10,0x03,0x00,0x00,0x00,0x00,
+ 0xbc,0x3e,0x07,0x02,0xc0,0x9b,0x01,0x20,
+ 0x00,0x00,0x00,0x00,0xdb,0xf8,0x00,0x20,
+ 0x98,0x3e,0x07,0x02,0x8b,0xaf,0x00,0x20,
+ 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe5,0xcd,0x16,0x00,0xe9,0xcd,0x16,0x00,
+ 0xe8,0x03,0x00,0x00,0x6c,0x55,0x01,0x20,
+ 0x2c,0x01,0x00,0x00,0x85,0xbb,0x00,0x20,
+ 0xe8,0x03,0x00,0x00,0xe9,0xcd,0x16,0x00,
+};
+
static const struct parade_write parade_writes[] = {
{ 0x02, 0xa1, 0x01 }, /* HPD low */
/*
@@ -176,6 +236,8 @@ static enum exynos5_gpio_pin bl_en = GPIO_X22; /* active high */
static void parade_dp_bridge_setup(void)
{
+ int i;
+
gpio_set_value(dp_pd_l, 1);
gpio_cfg_pin(dp_pd_l, GPIO_OUTPUT);
gpio_set_pull(dp_pd_l, GPIO_PULL_NONE);
@@ -186,6 +248,8 @@ static void parade_dp_bridge_setup(void)
udelay(10);
gpio_set_value(dp_rst_l, 1);
+
+ gpio_set_pull(dp_hpd, GPIO_PULL_NONE);
gpio_cfg_pin(dp_hpd, GPIO_INPUT);
/* De-assert PD (and possibly RST) to power up the bridge. */
@@ -199,9 +263,19 @@ static void parade_dp_bridge_setup(void)
exynos_pinmux_i2c7();
i2c_init(7, 100000, 0x00);
- parade_ps8625_bridge_setup(7, 0x48,
- parade_writes,
+ parade_ps8625_bridge_setup(7, 0x48, parade_writes,
ARRAY_SIZE(parade_writes));
+ /* Spin until the display is ready.
+ * It's quite important to try really hard to get the display up,
+ * so be generous. It will typically be ready in only 5 ms. and
+ * we're out of here.
+ * If it's not ready after a second, then we're in big trouble.
+ */
+ for(i = 0; i < 1000; i++){
+ if (gpio_get_value(dp_hpd))
+ break;
+ mdelay(1);
+ }
}
/*
@@ -230,22 +304,17 @@ static void backlight_en(void)
gpio_direction_output(bl_en, 1);
}
-//static struct video_info smdk5420_dp_config = {
-static struct video_info dp_video_info = {
- /* FIXME: fix video_info struct to use const for name */
- .name = (char *)"eDP-LVDS NXP PTN3460",
+
+static struct edp_video_info dp_video_info = {
+ .master_mode = 0,
.h_sync_polarity = 0,
.v_sync_polarity = 0,
.interlaced = 0,
-
.color_space = COLOR_RGB,
.dynamic_range = VESA,
.ycbcr_coeff = COLOR_YCBCR601,
.color_depth = COLOR_8,
-
- .link_rate = LINK_RATE_2_70GBPS,
- .lane_count = LANE_COUNT2,
};
/* FIXME: move some place more appropriate */
@@ -305,14 +374,13 @@ static void backlight_vdd(void)
/* this happens after cpu_init where exynos resources are set */
static void mainboard_init(device_t dev)
{
- struct s5p_dp_device dp_device = {
- .base = (struct exynos5_dp *)EXYNOS5420_DP1_BASE,
- .video_info = &dp_video_info,
- };
+ /* we'll stick with the crummy u-boot struct for now.*/
+ /* doing this as an auto since the struct has to be writeable */
+ struct edp_device_info device_info;
+
void *fb_addr = (void *)(get_fb_base_kb() * KiB);
gpio_init();
-
tmu_init(&exynos5420_tmu_info);
/* Clock Gating all the unused IP's to save power */
@@ -334,17 +402,30 @@ static void mainboard_init(device_t dev)
lcd_vdd();
+ /* Start the fimd running before you do the phy and lcd setup.
+ * why do fimd before training etc?
+ * because we need a data stream from
+ * the fimd or the clock recovery step fails.
+ */
+ vidinfo.screen_base = fb_addr;
+ exynos_fimd_lcd_init(&vidinfo);
+
parade_dp_bridge_setup();
- dp_controller_init(&dp_device);
+
+ /* this might get more dynamic in future ... */
+ memset(&device_info, 0, sizeof(device_info));
+ device_info.disp_info.name = (char *)"Pit display";
+ device_info.disp_info.h_total = 1366;
+ device_info.disp_info.v_total = 768;
+ device_info.video_info = dp_video_info;
+ device_info.raw_edid = panel_edid;
+ exynos_init_dp(&device_info);
udelay(LCD_T3_DELAY_MS * 1000);
backlight_vdd();
backlight_pwm();
backlight_en();
-
- // Uncomment to get excessive GPIO output:
- // gpio_info();
}
#if !CONFIG_DYNAMIC_CBMEM