summaryrefslogtreecommitdiff
path: root/src/cpu/samsung/exynos5250/fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/samsung/exynos5250/fb.c')
-rw-r--r--src/cpu/samsung/exynos5250/fb.c578
1 files changed, 0 insertions, 578 deletions
diff --git a/src/cpu/samsung/exynos5250/fb.c b/src/cpu/samsung/exynos5250/fb.c
deleted file mode 100644
index 080be49250..0000000000
--- a/src/cpu/samsung/exynos5250/fb.c
+++ /dev/null
@@ -1,578 +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 <delay.h>
-#include <stdlib.h>
-#include <string.h>
-#include <timer.h>
-#include <arch/io.h>
-#include <console/console.h>
-#include "power.h"
-#include "sysreg.h"
-
-#include "dp.h"
-#include "dp-core.h"
-#include "fimd.h"
-#include "i2c.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)
-{
- setbits_le32(&exynos_sysreg->disp1blk_cfg, FIMDBYPASS_DISP1);
- exynos_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;
-
- fb_size = ALIGN(fb_size, 4096);
-
- writel(pd->ivclk | pd->fixvclk, &exynos_disp_ctrl->vidcon1);
- val = ENVID_ON | ENVID_F_ON | (pd->clkval_f << CLKVAL_F_OFFSET);
- writel(val, &exynos_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, &exynos_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, &exynos_disp_ctrl->vidtcon1);
-
- val = ((pd->xres - 1) << HOZVAL_OFFSET) |
- ((pd->yres - 1) << LINEVAL_OFFSET);
- writel(val, &exynos_disp_ctrl->vidtcon2);
-
- writel((unsigned int)lcdbase, &exynos_fimd->vidw00add0b0);
- writel((unsigned int)lcdbase + fb_size, &exynos_fimd->vidw00add1b0);
-
- writel(pd->xres * 2, &exynos_fimd->vidw00add2);
-
- val = ((pd->xres - 1) << OSD_RIGHTBOTX_F_OFFSET);
- val |= ((pd->yres - 1) << OSD_RIGHTBOTY_F_OFFSET);
- writel(val, &exynos_fimd->vidosd0b);
- writel(pd->xres * pd->yres, &exynos_fimd->vidosd0c);
-
- setbits_le32(&exynos_fimd->shadowcon, CHANNEL0_EN);
-
- val = BPPMODE_F_RGB_16BIT_565 << BPPMODE_F_OFFSET;
- val |= ENWIN_F_ENABLE | HALF_WORD_SWAP_EN;
- writel(val, &exynos_fimd->wincon0);
-
- /* DPCLKCON_ENABLE */
- writel(1 << 1, &exynos_fimd->dpclkcon);
-}
-
-#ifdef UNUSED_CODE
-void exynos_fimd_disable(void)
-{
- writel(0, &exynos_fimd->wincon0);
- clrbits_le32(&exynos_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;
-}