Ronald G. Minnich (rminnich@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2570
-gerrit
commit c18f10339631fafb4138032f4da493642bfaedf8 Author: Ronald G. Minnich rminnich@gmail.com Date: Fri Mar 1 10:18:14 2013 -0800
samsung/exynos5: add display port defines and initialization functions.
These are essential functions for setting up the display port, and enable such things as aux channel communications.
Change-Id: I56400ec9016ecb8716ec5a5dae41fdfbfff4817a Signed-off-by: Ronald G. Minnich rminnich@gmail.com --- src/cpu/samsung/exynos5-common/Makefile.inc | 1 + src/cpu/samsung/exynos5-common/s5p-dp-core.h | 262 ++++++++++++++ src/cpu/samsung/exynos5-common/s5p-dp-reg.c | 480 +++++++++++++++++++++++++ src/cpu/samsung/exynos5-common/s5p-dp.h | 513 +++++++++++++++++++++++++++ 4 files changed, 1256 insertions(+)
diff --git a/src/cpu/samsung/exynos5-common/Makefile.inc b/src/cpu/samsung/exynos5-common/Makefile.inc index 47abe0f..d214c52 100644 --- a/src/cpu/samsung/exynos5-common/Makefile.inc +++ b/src/cpu/samsung/exynos5-common/Makefile.inc @@ -19,3 +19,4 @@ ramstage-y += pwm.c # needed by timer.c ramstage-y += timer.c ramstage-y += gpio.c ramstage-y += i2c.c +ramstage-y += s5p-dp-reg.c \ No newline at end of file diff --git a/src/cpu/samsung/exynos5-common/s5p-dp-core.h b/src/cpu/samsung/exynos5-common/s5p-dp-core.h new file mode 100644 index 0000000..582a7f4 --- /dev/null +++ b/src/cpu/samsung/exynos5-common/s5p-dp-core.h @@ -0,0 +1,262 @@ +/* + * Header file for Samsung DP (Display Port) interface driver. + * + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han jg1.han@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. + */ + +#ifndef _S5P_DP_CORE_H +#define _S5P_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); + +#ifdef CONFIG_EXYNOS_DISPLAYPORT +/* + * The following are board specific calls to implement the various + * STAGE_* steps. + * + * param blob Flattened device tree blob + * param wait_ms Set by the function to the next wait time + * return 0 on success, -EAGAIN to try again, others to fail + */ +extern int board_dp_lcd_vdd(const void *blob, unsigned *wait_ms); +extern int board_dp_bridge_setup(const void *blob, unsigned *wait_ms); +extern int board_dp_bridge_init(const void *blob, unsigned *wait_ms); +extern int board_dp_bridge_reset(const void *blob, unsigned *wait_ms); +extern int board_dp_hotplug(const void *blob, unsigned *wait_ms); +extern int board_dp_backlight_vdd(const void *blob, unsigned *wait_ms); +extern int board_dp_backlight_pwm(const void *blob, unsigned *wait_ms); +extern int board_dp_backlight_en(const void *blob, unsigned *wait_ms); +#endif +#endif /* _S5P_DP_CORE_H */ diff --git a/src/cpu/samsung/exynos5-common/s5p-dp-reg.c b/src/cpu/samsung/exynos5-common/s5p-dp-reg.c new file mode 100644 index 0000000..4a4614b --- /dev/null +++ b/src/cpu/samsung/exynos5-common/s5p-dp-reg.c @@ -0,0 +1,480 @@ +/* + * Samsung DP (Display port) register interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han jg1.han@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. + */ + +#include <common.h> +#include <arch/io.h> +#include <cpu/samsung/exynos5-common/clk.h> +#include <cpu/samsung/exynos5250/cpu.h> +#include <cpu/samsung/exynos5250/periph.h> +#include <cpu/samsung/exynos5250/s5p-dp.h> +#include "s5p-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; + u32 start; + 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); + + start = get_timer(0); + while (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + if (get_timer(start) > PLL_LOCK_TIMEOUT) { + debug("%s: PLL is not locked yet\n", __func__); + return -1; + } + } + } + + /* 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) { + 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) { + debug("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 + 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 + 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) { + 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; + u32 start; + struct exynos5_dp *base = dp->base; + + /* Wait for 4 VSYNC_DET interrupts */ + start = get_timer(0); + 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; + } while (get_timer(start) <= STREAM_ON_TIMEOUT); + + if (i != 4) { + 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/exynos5-common/s5p-dp.h b/src/cpu/samsung/exynos5-common/s5p-dp.h new file mode 100644 index 0000000..5322383 --- /dev/null +++ b/src/cpu/samsung/exynos5-common/s5p-dp.h @@ -0,0 +1,513 @@ +/* + * (C) Copyright 2012 Samsung Electronics + * Register map for Exynos5 DP + * + * 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 + */ + +#ifndef __EXYNOS5_DP_H__ +#define __EXYNOS5_DP_H__ + +/* DSIM register map */ +struct exynos5_dp { + unsigned char res1[0x10]; + unsigned int dp_tx_version; + unsigned int dp_tx_sw_reset; + unsigned int func_en_1; + unsigned int func_en_2; + unsigned int video_ctl_1; + unsigned int video_ctl_2; + unsigned int video_ctl_3; + unsigned int video_ctl_4; + unsigned int clr_blue_cb; + unsigned int clr_green_y; + unsigned int clr_red_cr; + unsigned int video_ctl_8; + unsigned char res2[0x4]; + unsigned int video_ctl_10; + unsigned int total_line_l; + unsigned int total_line_h; + unsigned int active_line_l; + unsigned int active_line_h; + unsigned int v_f_porch; + unsigned int vsync; + unsigned int v_b_porch; + unsigned int total_pixel_l; + unsigned int total_pixel_h; + unsigned int active_pixel_l; + unsigned int active_pixel_h; + unsigned int h_f_porch_l; + unsigned int h_f_porch_h; + unsigned int hsync_l; + unsigned int hysnc_h; + unsigned int h_b_porch_l; + unsigned int h_b_porch_h; + unsigned int vid_status; + unsigned int total_line_sta_l; + unsigned int total_line_sta_h; + unsigned int active_line_sta_l; + unsigned int active_line_sta_h; + unsigned int v_f_porch_sta; + unsigned int vsync_sta; + unsigned int v_b_porch_sta; + unsigned int total_pixel_sta_l; + unsigned int total_pixel_sta_h; + unsigned int active_pixel_sta_l; + unsigned int active_pixel_sta_h; + unsigned int h_f_porch_sta_l; + unsigned int h_f_porch_sta_h; + unsigned int hsync_sta_l; + unsigned int hsync_sta_h; + unsigned int h_b_porch_sta_l; + unsigned int h_b_porch__sta_h; + unsigned char res3[0x288]; + unsigned int lane_map; + unsigned char res4[0x10]; + unsigned int analog_ctl_1; + unsigned int analog_ctl_2; + unsigned int analog_ctl_3; + unsigned int pll_filter_ctl_1; + unsigned int tx_amp_tuning_ctl; + unsigned char res5[0xc]; + unsigned int aux_hw_retry_ctl; + unsigned char res6[0x2c]; + unsigned int int_state; + unsigned int common_int_sta_1; + unsigned int common_int_sta_2; + unsigned int common_int_sta_3; + unsigned int common_int_sta_4; + unsigned char res7[0x8]; + unsigned int dp_int_sta; + unsigned int common_int_mask_1; + unsigned int common_int_mask_2; + unsigned int common_int_mask_3; + unsigned int common_int_mask_4; + unsigned char res8[0x08]; + unsigned int int_sta_mask; + unsigned int int_ctl; + unsigned char res9[0x200]; + unsigned int sys_ctl_1; + unsigned int sys_ctl_2; + unsigned int sys_ctl_3; + unsigned int sys_ctl_4; + unsigned int dp_vid_ctl; + unsigned char res10[0x2c]; + unsigned int pkt_send_ctl; + unsigned char res11[0x4]; + unsigned int dp_hdcp_ctl; + unsigned char res12[0x34]; + unsigned int link_bw_set; + unsigned int lane_count_set; + unsigned int dp_training_ptn_set; + unsigned int ln0_link_trn_ctl; + unsigned int ln1_link_trn_ctl; + unsigned int ln2_link_trn_ctl; + unsigned int ln3_link_trn_ctl; + unsigned int dp_dn_spread; + unsigned int dp_hw_link_training; + unsigned char res13[0x1c]; + unsigned int dp_debug_ctl; + unsigned int dp_hpd_deglitch_l; + unsigned int dp_hpd_deglitch_h; + unsigned char res14[0x14]; + unsigned int dp_link_debug_ctl; + unsigned char res15[0x1c]; + unsigned int m_vid_0; + unsigned int m_vid_1; + unsigned int m_vid_2; + unsigned int n_vid_0; + unsigned int n_vid_1; + unsigned int n_vid_2; + unsigned int m_vid_mon; + unsigned int dp_pll_ctl; + unsigned int dp_phy_pd; + unsigned int dp_phy_test; + unsigned char res16[0x8]; + unsigned int dp_video_fifo_thrd; + unsigned char res17[0x8]; + unsigned int dp_audio_margin; + unsigned int dp_dn_spread_ctl_1; + unsigned int dp_dn_spread_ctl_2; + unsigned char res18[0x18]; + unsigned int dp_m_cal_ctl; + unsigned int m_vid_gen_filter_th; + unsigned char res19[0x14]; + unsigned int m_aud_gen_filter_th; + unsigned int aux_ch_sta; + unsigned int aux_err_num; + unsigned int aux_ch_defer_dtl; + unsigned int aux_rx_comm; + unsigned int buf_data_ctl; + unsigned int aux_ch_ctl_1; + unsigned int aux_addr_7_0; + unsigned int aux_addr_15_8; + unsigned int aux_addr_19_16; + unsigned int aux_ch_ctl_2; + unsigned char res20[0x18]; + unsigned int buf_data_0; + unsigned char res21[0x3c]; + unsigned int soc_general_ctl; +}; +/* 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) +#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_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_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) + +/* DP_VIDEO_CTL_3 */ +#define IN_YC_COEFFI_MASK (1 << 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 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) + +/* DP_AUX_CH_DEFER_CTL */ +#define DEFER_CTRL_EN (1 << 7) +#define DEFER_COUNT_SHIFT 0 +#define DEFER_COUNT_MASK 0x7f + +/* DP_AUX_RX_COMM */ +#define AUX_RX_COMM_I2C_DEFER (2 << 2) +#define AUX_RX_COMM_AUX_DEFER (2 << 0) + +/* DP_BUFFER_DATA_CTL */ +#define BUF_CLR (1 << 7) + +/* Maximum number of tries for Aux Transaction */ +#define MAX_AUX_RETRY_COUNT 10 + +/* DP_AUX_CH_CTL_1 */ +#define AUX_LENGTH_SHIFT 4 +#define AUX_LENGTH_MASK 0xf + +#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) + +/* 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 + +/* 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); + +/** + * Perform the next stage of the LCD init if it is time to do so. + * + * LCD init can be time-consuming because of the number of delays we need + * while waiting for the backlight power supply, etc. This function can + * be called at various times during U-Boot operation to advance the + * initialization of the LCD to the next stage if sufficient time has + * passed since the last stage. It keeps track of what stage it is up to + * and the time that it is permitted to move to the next stage. + * + * The final call should have can_block=1 to complete the init. + * + * @param blob fdt blob containing LCD information + * @param can_block 1 to wait until all init is complete, and then return + * 0 to return immediately, potentially doing nothing if it + * is not yet time for the next init. + */ +int exynos_lcd_check_next_stage(const void *blob, int can_block); +#endif