summaryrefslogtreecommitdiff
path: root/src/drivers/intel
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/intel')
-rw-r--r--src/drivers/intel/gma/Kconfig6
-rw-r--r--src/drivers/intel/gma/Makefile.inc1
-rw-r--r--src/drivers/intel/gma/display.c119
-rw-r--r--src/drivers/intel/gma/drm_dp_helper.c119
-rw-r--r--src/drivers/intel/gma/i915.h200
-rw-r--r--src/drivers/intel/gma/intel_ddi.c156
-rw-r--r--src/drivers/intel/gma/intel_dp.c1622
7 files changed, 0 insertions, 2223 deletions
diff --git a/src/drivers/intel/gma/Kconfig b/src/drivers/intel/gma/Kconfig
index df45083b5c..1e60a425da 100644
--- a/src/drivers/intel/gma/Kconfig
+++ b/src/drivers/intel/gma/Kconfig
@@ -14,12 +14,6 @@
## GNU General Public License for more details.
##
-config INTEL_DP
- bool
- default n
- help
- helper functions for intel display port operations
-
config INTEL_DDI
bool
default n
diff --git a/src/drivers/intel/gma/Makefile.inc b/src/drivers/intel/gma/Makefile.inc
index d4d6c08842..502ae08654 100644
--- a/src/drivers/intel/gma/Makefile.inc
+++ b/src/drivers/intel/gma/Makefile.inc
@@ -13,7 +13,6 @@
## GNU General Public License for more details.
##
-ramstage-$(CONFIG_INTEL_DP) += intel_dp.c drm_dp_helper.c display.c
ramstage-$(CONFIG_INTEL_DDI) += intel_ddi.c
ramstage-$(CONFIG_INTEL_EDID) += edid.c vbt.c
ifeq ($(CONFIG_VGA_ROM_RUN),y)
diff --git a/src/drivers/intel/gma/display.c b/src/drivers/intel/gma/display.c
deleted file mode 100644
index afcec91d4c..0000000000
--- a/src/drivers/intel/gma/display.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Keith Packard <keithp@keithp.com>
- *
- */
-
-/* This code was created by the coccinnelle filters in the i915tool,
- * with some final hand filtering.
- */
-
-#include <console/console.h>
-#include <stdint.h>
-#include <delay.h>
-#include <drivers/intel/gma/i915.h>
-#include <string.h>
-
-void compute_display_params(struct intel_dp *dp)
-{
- struct edid *edid = &(dp->edid);
- struct edid_mode *mode = &edid->mode;
-
- /* step 1: get the constants in the dp struct set up. */
- dp->lane_count = dp->dpcd[DP_MAX_LANE_COUNT]&DP_LANE_COUNT_MASK;
-
- dp->link_bw = dp->dpcd[DP_MAX_LINK_RATE];
- dp->clock = intel_dp_bw_code_to_link_rate(dp->link_bw);
- dp->edid.link_clock = intel_dp_bw_code_to_link_rate(dp->link_bw);
-
- /* step 2. Do some computation of other stuff. */
- dp->bytes_per_pixel = dp->pipe_bits_per_pixel/8;
-
- dp->stride = edid->bytes_per_line;
-
- dp->htotal = (mode->ha - 1) | ((mode->ha + mode->hbl - 1) << 16);
-
- dp->hblank = (mode->ha - 1) | ((mode->ha + mode->hbl - 1) << 16);
-
- dp->hsync = (mode->ha + mode->hso - 1) |
- ((mode->ha + mode->hso + mode->hspw - 1) << 16);
-
- dp->vtotal = (mode->va - 1) | ((mode->va + mode->vbl - 1) << 16);
-
- dp->vblank = (mode->va - 1) | ((mode->va + mode->vbl - 1) << 16);
-
- dp->vsync = (mode->va + mode->vso - 1) |
- ((mode->va + mode->vso + mode->vspw - 1) << 16);
-
- /* PIPEASRC is wid-1 x ht-1 */
- dp->pipesrc = (mode->ha-1)<<16 | (mode->va-1);
-
- dp->pfa_pos = 0;
-
- dp->pfa_ctl = PF_ENABLE | PF_FILTER_MED_3x3;
- /* IVB hack */
- if (dp->gen == 6)
- dp->pfa_ctl |= PF_PIPE_SEL_IVB(dp->pipe);
-
- dp->pfa_sz = (mode->ha << 16) | (mode->va);
-
- /* step 3. Call the linux code we pulled in. */
- dp->flags = intel_ddi_calc_transcoder_flags(edid->panel_bits_per_pixel,
- dp->port,
- dp->pipe,
- dp->type,
- dp->lane_count,
- dp->pfa_sz,
- mode->phsync == '+'?1:0,
- mode->pvsync == '+'?1:0);
-
- dp->transcoder = intel_ddi_get_transcoder(dp->port,
- dp->pipe);
-
- intel_dp_compute_m_n(edid->panel_bits_per_pixel,
- dp->lane_count,
- dp->edid.mode.pixel_clock,
- dp->edid.link_clock,
- &dp->m_n);
-
- printk(BIOS_SPEW, "dp->lane_count = 0x%08x\n",dp->lane_count);
- printk(BIOS_SPEW, "dp->stride = 0x%08x\n",dp->stride);
- printk(BIOS_SPEW, "dp->htotal = 0x%08x\n", dp->htotal);
- printk(BIOS_SPEW, "dp->hblank = 0x%08x\n", dp->hblank);
- printk(BIOS_SPEW, "dp->hsync = 0x%08x\n", dp->hsync);
- printk(BIOS_SPEW, "dp->vtotal = 0x%08x\n", dp->vtotal);
- printk(BIOS_SPEW, "dp->vblank = 0x%08x\n", dp->vblank);
- printk(BIOS_SPEW, "dp->vsync = 0x%08x\n", dp->vsync);
- printk(BIOS_SPEW, "dp->pipesrc = 0x%08x\n", dp->pipesrc);
- printk(BIOS_SPEW, "dp->pfa_pos = 0x%08x\n", dp->pfa_pos);
- printk(BIOS_SPEW, "dp->pfa_ctl = 0x%08x\n", dp->pfa_ctl);
- printk(BIOS_SPEW, "dp->pfa_sz = 0x%08x\n", dp->pfa_sz);
- printk(BIOS_SPEW, "dp->link_m = 0x%08x\n", dp->m_n.link_m);
- printk(BIOS_SPEW, "dp->link_n = 0x%08x\n", dp->m_n.link_n);
- printk(BIOS_SPEW, "0x6f030 = 0x%08x\n",
- TU_SIZE(dp->m_n.tu) | dp->m_n.gmch_m);
- printk(BIOS_SPEW, "0x6f030 = 0x%08x\n", dp->m_n.gmch_m);
- printk(BIOS_SPEW, "0x6f034 = 0x%08x\n", dp->m_n.gmch_n);
- printk(BIOS_SPEW, "dp->flags = 0x%08x\n", dp->flags);
-}
diff --git a/src/drivers/intel/gma/drm_dp_helper.c b/src/drivers/intel/gma/drm_dp_helper.c
deleted file mode 100644
index 66072263f4..0000000000
--- a/src/drivers/intel/gma/drm_dp_helper.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- * Copyright © 2009 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-#include <console/console.h>
-#include <stdint.h>
-#include <delay.h>
-#include <drivers/intel/gma/i915.h>
-#include <string.h>
-
-#include <edid.h>
-
-/* reduced a lot for coreboot. */
-/**
- * DOC: dp helpers
- *
- * These functions contain some common logic and helpers at various
- * abstraction levels to deal with Display Port sink devices and
- * related things like DP aux channel transfers, EDID reading over DP
- * aux channels, decoding certain DPCD blocks, ...
- */
-
-
-/* Helpers for DP link training */
-static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r)
-{
- printk(BIOS_SPEW, "%s: %d, %d, %d\n", __func__,
- r, r - DP_LANE0_1_STATUS,
- link_status[r - DP_LANE0_1_STATUS]);
- return link_status[r - DP_LANE0_1_STATUS];
-}
-
-static u8 dp_get_lane_status(u8 link_status[DP_LINK_STATUS_SIZE],
- int lane)
-{
- int i = DP_LANE0_1_STATUS + (lane >> 1);
- int s = (lane & 1) * 4;
- u8 l = dp_link_status(link_status, i);
- return (l >> s) & 0xf;
-}
-
-int drm_dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE],
- int lane_count)
-{
- u8 lane_align;
- u8 lane_status;
- int lane;
-
- lane_align = dp_link_status(link_status,
- DP_LANE_ALIGN_STATUS_UPDATED);
- if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
- return 0;
- for (lane = 0; lane < lane_count; lane++) {
- lane_status = dp_get_lane_status(link_status, lane);
- if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS)
- return 0;
- }
- return 1;
-}
-
-int drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE],
- int lane_count)
-{
- int lane;
- u8 lane_status;
-
- for (lane = 0; lane < lane_count; lane++) {
- lane_status = dp_get_lane_status(link_status, lane);
- if ((lane_status & DP_LANE_CR_DONE) == 0)
- return 0;
- }
- return 1;
-}
-
-u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE],
- int lane)
-{
- int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
- int s = ((lane & 1) ?
- DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
- DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
- u8 l = dp_link_status(link_status, i);
-
- printk(BIOS_SPEW, "%s: i %d s %d l %d return %d\n",
- __func__, i, s, l,
- ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT);
- return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
-}
-
-u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
- int lane)
-{
- int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
- int s = ((lane & 1) ?
- DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
- DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
- u8 l = dp_link_status(link_status, i);
-
- return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
-}
diff --git a/src/drivers/intel/gma/i915.h b/src/drivers/intel/gma/i915.h
index d9bb940fa4..9a2acdb96b 100644
--- a/src/drivers/intel/gma/i915.h
+++ b/src/drivers/intel/gma/i915.h
@@ -81,201 +81,7 @@ enum {
unsigned long io_i915_read32(unsigned long addr);
void io_i915_write32(unsigned long val, unsigned long addr);
-/*
- * To communicate to and control the extracted-from-kernel code,
- * we need this struct. It has a counterpart in the ARM code, so
- * there is a precedent.
- */
-
-#define DP_RECEIVER_CAP_SIZE 0xf
-#define DP_LINK_STATUS_SIZE 6
-#define DP_LINK_CHECK_TIMEOUT (10 * 1000)
-
-#define DP_LINK_CONFIGURATION_SIZE 9
-
-struct intel_dp_m_n {
- uint32_t tu;
- uint32_t gmch_m;
- uint32_t gmch_n;
- uint32_t link_m;
- uint32_t link_n;
-};
-
-struct intel_dp {
- int gen; // 6 for link, 7 for wtm2
- int has_pch_split; // 1 for link and wtm2
- int has_pch_cpt; // 1 for everything we know about.
- int is_haswell;
- /* output register offset in MMIO space. Usually DP_A */
- u32 output_reg;
- /* The initial value of the DP register.
- * Mainboards can set this to a non-zero
- * value in the case that there are undetectable
- * but essential parameters.
- */
- u32 DP;
- uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE];
- u32 color_range;
- /* these paramaters are determined after reading the DPCD */
- int dpms_mode;
- uint8_t link_bw;
- uint8_t lane_count;
- /* This data is read from the panel via the AUX channel.*/
- uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
- int type;
- int edp;
- int is_pch_edp;
- /* state related to training. */
- uint8_t train_set[4];
- /* Determined from EDID or coreboot hard-sets. */
- int panel_power_up_delay;
- int panel_power_down_delay;
- int panel_power_cycle_delay;
- int backlight_on_delay;
- int backlight_off_delay;
- int want_panel_vdd;
- u32 clock;
- int port;
- int pipe;
- int plane;
- int pipe_bits_per_pixel;
- /* i2c on aux is ... interesting.
- * Before you do an i2c cycle, you need to set the address.
- * This requires we remember it from one moment to the next.
- * Remember it here.
- */
- u16 address;
- /* timing parameters for aux channel IO. They used to compute these on
- * each and every entry to the functions, which is kind of stupid, and it had
- * errors anyway.
- * note: you can get these from watching YABEL output. E.g.:
- * you see an outb of 0x802300e1 to 64010. the 3 is the precharge
- * and the e1 is the clock divider.
- */
- u32 aux_clock_divider;
- u32 precharge;
- /* EDID, raw and processed */
- u8 rawedid[256];
- int edidlen;
- struct edid edid;
- /* computed values needed for "i915" registers */
- int bytes_per_pixel;
- u32 htotal;
- u32 hblank;
- u32 hsync;
- u32 vtotal;
- u32 vblank;
- u32 vsync;
- u32 pfa_sz;
- u32 pfa_pos;
- u32 pfa_ctl;
- u32 pipesrc;
- u32 stride;
- struct intel_dp_m_n m_n;
- u32 flags;
- u32 transcoder;
- /* parameters computed by the early startup, to be used
- * in the GMA code.
- */
- u8 *graphics;
- /* physical address, not to be used directly. */
- u64 physbase;
-};
-
-/* we may yet need these. */
-void intel_dp_mode_set(struct intel_dp *intel_dp);
-void intel_dp_start_link_train(struct intel_dp *intel_dp);
-
-int intel_dp_i2c_init(struct intel_dp *intel_dp);
-int intel_dp_i2c_aux_ch(struct intel_dp *intel_dp,
- int mode, uint8_t write_byte, uint8_t *read_byte);
-
-int intel_dp_get_dpcd(struct intel_dp *intel_dp);
-struct edid *intel_dp_get_edid(struct intel_dp *intel_dp);
-
-void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
-void ironlake_edp_pll_on(void);
-void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
-void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, int sync);
-int intel_dp_get_max_downspread(struct intel_dp *intel_dp, u8 *max_downspread);
-void ironlake_edp_panel_on(struct intel_dp *intel_dp);
-void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
-/* needed only on haswell. */
-void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, int port);
-int intel_dp_aux_ch(struct intel_dp *intel_dp,
- uint8_t *send, int send_bytes,
- uint8_t *recv, int recv_size);
-void unpack_aux(u32 src, uint8_t *dst, int dst_bytes);
-int intel_channel_eq_ok(struct intel_dp *intel_dp,
- uint8_t link_status[DP_LINK_STATUS_SIZE]);
-void ironlake_edp_panel_off(struct intel_dp *intel_dp);
-void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
-
-/* drm_dp_helper.c */
-int drm_dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE],
- int lane_count);
-int drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE],
- int lane_count);
-u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE],
- int lane);
-u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
- int lane);
-
-
-void intel_dp_wait_reg(unsigned long addr,
- unsigned long val);
-
-void intel_dp_wait_panel_power_control(unsigned long val);
-
-void intel_dp_compute_m_n(unsigned int bits_per_pixel,
- unsigned int nlanes,
- unsigned int pixel_clock,
- unsigned int link_clock,
- struct intel_dp_m_n *m_n);
-
-u32 intel_ddi_calc_transcoder_flags(u32 pipe_bpp,
- enum port port,
- enum pipe pipe,
- int type,
- int lane_count,
- int pf_sz,
- u8 phsync,
- u8 pvsync);
-
-enum transcoder intel_ddi_get_transcoder(enum port port,
- enum pipe pipe);
-
-void intel_dp_set_m_n_regs(struct intel_dp *intel_dp);
-int intel_dp_bw_code_to_link_rate(u8 link_bw);
-void intel_dp_set_resolution(struct intel_dp *intel_dp);
-
-int intel_dp_i2c_write(struct intel_dp *intel_dp,
- u8 val);
-
-int intel_dp_i2c_read(struct intel_dp *intel_dp,
- u8 *val);
-
-int intel_dp_set_bw(struct intel_dp *intel_dp);
-int intel_dp_set_lane_count(struct intel_dp *intel_dp);
-int intel_dp_set_training_lane0(struct intel_dp *intel_dp,
- u8 val);
-int intel_dp_set_training_pattern(struct intel_dp *intel_dp,
- u8 pat);
-
-int intel_dp_get_link_status(struct intel_dp *intel_dp,
- uint8_t link_status[DP_LINK_STATUS_SIZE]);
-
-int intel_dp_get_training_pattern(struct intel_dp *intel_dp,
- u8 *recv);
-
-int intel_dp_get_lane_count(struct intel_dp *intel_dp,
- u8 *recv);
-
-int intel_dp_get_lane_align_status(struct intel_dp *intel_dp,
- u8 *recv);
-
void intel_prepare_ddi(void);
-void intel_ddi_set_pipe_settings(struct intel_dp *intel_dp);
int gtt_poll(u32 reg, u32 mask, u32 value);
void gtt_write(u32 reg, u32 data);
@@ -295,14 +101,8 @@ drivers_intel_gma_displays_ssdt_generate(const struct i915_gpu_controller_info *
const struct i915_gpu_controller_info *
intel_gma_get_controller_info(void);
-int i915lightup(unsigned int physbase, unsigned int mmio,
- unsigned int gfx, unsigned int init_fb);
-int panel_lightup(struct intel_dp *dp, unsigned int init_fb);
void *igd_make_opregion(void);
-/* display.c */
-void compute_display_params(struct intel_dp *dp);
-
/* vbt.c */
struct device;
void
diff --git a/src/drivers/intel/gma/intel_ddi.c b/src/drivers/intel/gma/intel_ddi.c
index 9127060ece..c01aef45c9 100644
--- a/src/drivers/intel/gma/intel_ddi.c
+++ b/src/drivers/intel/gma/intel_ddi.c
@@ -114,159 +114,3 @@ void intel_prepare_ddi(void)
intel_prepare_ddi_buffers(PORT_E, use_fdi);
}
-
-static void intel_wait_ddi_buf_idle(int port)
-{
- uint32_t reg = DDI_BUF_CTL(port);
- int i;
-
- for (i = 0; i < 8; i++) {
- udelay(1);
- if (gtt_read(reg) & DDI_BUF_IS_IDLE){
- printk(BIOS_SPEW, "%s: buf is idle (success)\n", __func__);
- return;
- }
- }
- printk(BIOS_ERR, "Timeout waiting for DDI BUF %d idle bit\n", port);
-}
-
-
-void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, int port)
-{
- int wait = 0;
- uint32_t val;
-
- if (gtt_read(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) {
- val = gtt_read(DDI_BUF_CTL(port));
- if (val & DDI_BUF_CTL_ENABLE) {
- val &= ~DDI_BUF_CTL_ENABLE;
- gtt_write(val,DDI_BUF_CTL(port));
- wait = 1;
- }
-
- val = gtt_read(DP_TP_CTL(port));
- val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
- val |= DP_TP_CTL_LINK_TRAIN_PAT1;
- gtt_write(val,DP_TP_CTL(port));
- //POSTING_READ(DP_TP_CTL(port));
-
- if (wait)
- intel_wait_ddi_buf_idle(port);
- }
-
- val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST |
- DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
- if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
- val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
- gtt_write(val,DP_TP_CTL(port));
- //POSTING_READ(DP_TP_CTL(port));
-
- intel_dp->DP |= DDI_BUF_CTL_ENABLE;
- gtt_write(intel_dp->DP,DDI_BUF_CTL(port));
- //POSTING_READ(DDI_BUF_CTL(port));
-
- udelay(600);
-}
-
-u32 intel_ddi_calc_transcoder_flags(u32 pipe_bpp,
- enum port port,
- enum pipe pipe,
- int type,
- int lane_count,
- int pf_sz,
- u8 phsync,
- u8 pvsync)
-{
- u32 temp;
-
- temp = TRANS_DDI_FUNC_ENABLE;
- temp |= TRANS_DDI_SELECT_PORT(port);
-
- switch (pipe_bpp) {
- case 18:
- temp |= TRANS_DDI_BPC_6;
- break;
- case 24:
- temp |= TRANS_DDI_BPC_8;
- break;
- case 30:
- temp |= TRANS_DDI_BPC_10;
- break;
- case 36:
- temp |= TRANS_DDI_BPC_12;
- break;
- default:
- printk(BIOS_ERR, "Invalid pipe_bpp: %d, *** Initialization will not succeed ***\n", pipe_bpp);
- }
-
- if (port == PORT_A) {
- switch (pipe) {
- case PIPE_A:
- if (pf_sz)
- temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
- else
- temp |= TRANS_DDI_EDP_INPUT_A_ON;
- break;
- case PIPE_B:
- temp |= TRANS_DDI_EDP_INPUT_B_ONOFF;
- break;
- case PIPE_C:
- temp |= TRANS_DDI_EDP_INPUT_C_ONOFF;
- break;
- default:
- printk(BIOS_ERR, "Invalid pipe %d\n", pipe);
- }
- }
-
- if (phsync)
- temp |= TRANS_DDI_PHSYNC;
-
- if (pvsync)
- temp |= TRANS_DDI_PVSYNC;
-
- if (type == INTEL_OUTPUT_HDMI) {
- /* Need to understand when to set TRANS_DDI_MODE_SELECT_HDMI / TRANS_DDI_MODE_SELECT_DVI */
- } else if (type == INTEL_OUTPUT_ANALOG) {
- /* Set TRANS_DDI_MODE_SELECT_FDI with lane_count */
- } else if (type == INTEL_OUTPUT_DISPLAYPORT ||
- type == INTEL_OUTPUT_EDP) {
- temp |= TRANS_DDI_MODE_SELECT_DP_SST;
-
- temp |= DDI_PORT_WIDTH(lane_count);
- } else {
- printk(BIOS_ERR, "Invalid type %d for pipe\n", type);
- }
-
- return temp;
-}
-
-enum transcoder intel_ddi_get_transcoder(enum port port,
- enum pipe pipe)
-{
- if (port == PORT_A)
- return TRANSCODER_EDP;
- return (enum transcoder)pipe;
-}
-
-void intel_ddi_set_pipe_settings(struct intel_dp *intel_dp)
-{
- u32 val = TRANS_MSA_SYNC_CLK;
-
- switch (intel_dp->pipe_bits_per_pixel) {
- case 18:
- val |= TRANS_MSA_6_BPC;
- break;
- case 24:
- val |= TRANS_MSA_8_BPC;
- break;
- case 30:
- val |= TRANS_MSA_10_BPC;
- break;
- case 36:
- val |= TRANS_MSA_12_BPC;
- break;
- default:
- printk(BIOS_ERR, "Invalid bpp settings %d\n", intel_dp->pipe_bits_per_pixel);
- }
- gtt_write(TRANS_MSA_MISC(intel_dp->transcoder),val);
-}
diff --git a/src/drivers/intel/gma/intel_dp.c b/src/drivers/intel/gma/intel_dp.c
deleted file mode 100644
index 56ee73b7e2..0000000000
--- a/src/drivers/intel/gma/intel_dp.c
+++ /dev/null
@@ -1,1622 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- * Copyright © 2008 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Keith Packard <keithp@keithp.com>
- *
- */
-
-/* This code was created by the coccinnelle filters in the i915tool,
- * with some final hand filtering.
- */
-
-#include <console/console.h>
-#include <stdint.h>
-#include <delay.h>
-#include <drivers/intel/gma/i915.h>
-#include <string.h>
-
-/**
- * is_edp - is the given port attached to an eDP panel (either CPU or PCH)
- * @param intel_dp: DP struct
- *
- * If a CPU or PCH DP output is attached to an eDP panel, this function
- * will return 1, and 0 otherwise.
- */
-static int is_edp(struct intel_dp *intel_dp)
-{
- return intel_dp->type == INTEL_OUTPUT_EDP;
-}
-
-/**
- * is_pch_edp - is the port on the PCH and attached to an eDP panel?
- * @param intel_dp: DP struct
- *
- * Returns 1 if the given DP struct corresponds to a PCH DP port attached
- * to an eDP panel, 0 otherwise. Helpful for determining whether we
- * may need FDI resources for a given DP output or not.
- */
-static int is_pch_edp(struct intel_dp *intel_dp)
-{
- return intel_dp->is_pch_edp;
-}
-
-/**
- * is_cpu_edp - is the port on the CPU and attached to an eDP panel?
- * @param intel_dp: DP struct
- *
- * Returns 1 if the given DP struct corresponds to a CPU eDP port.
- */
-static int is_cpu_edp(struct intel_dp *intel_dp)
-{
- return is_edp(intel_dp) && !is_pch_edp(intel_dp);
-}
-
-static uint32_t
-pack_aux(uint8_t *src, int src_bytes)
-{
- int i;
- uint32_t v = 0;
-
- if (src_bytes > 4)
- src_bytes = 4;
- for (i = 0; i < src_bytes; i++)
- v |= ((uint32_t) src[i]) << ((3-i) * 8);
- return v;
-}
-
-void
-unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes)
-{
- int i;
- if (dst_bytes > 4)
- dst_bytes = 4;
- for (i = 0; i < dst_bytes; i++)
- dst[i] = src >> ((3-i) * 8);
-}
-
-static int ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
-{
-
- return (gtt_read(PCH_PP_STATUS) & PP_ON) != 0;
-}
-
-static int ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
-{
- return (gtt_read(PCH_PP_CONTROL) & EDP_FORCE_VDD) != 0;
-}
-
-int
-intel_dp_aux_ch(struct intel_dp *intel_dp,
- uint8_t *send, int send_bytes,
- uint8_t *recv, int recv_size)
-{
- uint32_t output_reg = intel_dp->output_reg;
- uint32_t ch_ctl = output_reg + 0x10;
- uint32_t ch_data = ch_ctl + 4;
- int i;
- int recv_bytes;
- uint32_t status;
- int try;
-
- /* Try to wait for any previous AUX channel activity */
- for (try = 0; try < 3; try++) {
- status = gtt_read(ch_ctl);
- if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
- break;
- mdelay(1);
- }
-
- if (try == 3) {
- if (1) {
- status = gtt_read(ch_ctl);
- printk(BIOS_ERR,
- "dp_aux_ch not started status 0x%08x\n",
- status);
- }
- return -1;
- }
-
- /* Must try at least 3 times according to DP spec */
- for (try = 0; try < 5; try++) {
- /* Load the send data into the aux channel data registers */
- for (i = 0; i < send_bytes; i += 4){
- u32 val, addr;
- val = pack_aux(send + i, send_bytes - i);
- addr = ch_data + i;
- gtt_write(addr,val);
- }
-
- /* Send the command and wait for it to complete */
- gtt_write(ch_ctl, DP_AUX_CH_CTL_SEND_BUSY |
- DP_AUX_CH_CTL_TIME_OUT_400us |
- (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
- (intel_dp->precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
- (intel_dp->aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
- DP_AUX_CH_CTL_DONE |
- DP_AUX_CH_CTL_TIME_OUT_ERROR |
- DP_AUX_CH_CTL_RECEIVE_ERROR);
- for (;;) {
- status = gtt_read(ch_ctl);
- if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
- break;
- udelay(100);
- }
-
- /* Clear done status and any errors */
- gtt_write(ch_ctl, status |
- DP_AUX_CH_CTL_DONE |
- DP_AUX_CH_CTL_TIME_OUT_ERROR |
- DP_AUX_CH_CTL_RECEIVE_ERROR);
-
- if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR |
- DP_AUX_CH_CTL_RECEIVE_ERROR))
- continue;
- if (status & DP_AUX_CH_CTL_DONE)
- break;
- }
-
- if ((status & DP_AUX_CH_CTL_DONE) == 0) {
- printk(BIOS_ERR, "dp_aux_ch not done status 0x%08x\n", status);
- return -1;
- }
-
- /* Check for timeout or receive error.
- * Timeouts occur when the sink is not connected
- */
- if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
- printk(BIOS_ERR,
- "dp_aux_ch receive error status 0x%08x\n", status);
- return -1;
- }
-
- /* Timeouts occur when the device isn't connected, so they're
- * "normal" -- don't fill the kernel log with these */
- if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
- printk(BIOS_ERR, "dp_aux_ch timeout status 0x%08x\n", status);
- return -1;
- }
-
- /* Unload any bytes sent back from the other side */
- recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
- DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
- if (recv_bytes > recv_size)
- recv_bytes = recv_size;
-
- for (i = 0; i < recv_bytes; i += 4)
- unpack_aux(gtt_read(ch_data + i),
- recv + i, recv_bytes - i);
-
- return recv_bytes;
-}
-
-/* Write data to the aux channel in native mode */
-static int
-intel_dp_aux_native_write(struct intel_dp *intel_dp,
- uint16_t address, uint8_t *send, int send_bytes)
-{
- int ret;
- uint8_t msg[20];
- int msg_bytes;
- uint8_t ack;
-
- if (send_bytes > 16)
- return -1;
- msg[0] = AUX_NATIVE_WRITE << 4;
- msg[1] = address >> 8;
- msg[2] = address & 0xff;
- msg[3] = send_bytes - 1;
- memcpy(&msg[4], send, send_bytes);
- msg_bytes = send_bytes + 4;
- for (;;) {
- ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
- if (ret < 0)
- return ret;
- if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
- break;
- else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
- udelay(100);
- else
- return -1;
- }
- return send_bytes;
-}
-
-/* Write a single byte to the aux channel in native mode */
-static int
-intel_dp_aux_native_write_1(struct intel_dp *intel_dp,
- uint16_t address, uint8_t byte)
-{
- return intel_dp_aux_native_write(intel_dp, address, &byte, 1);
-}
-
-int intel_dp_set_bw(struct intel_dp *intel_dp)
-{
- printk(BIOS_SPEW, "DP_LINK_BW_SET");
- return intel_dp_aux_native_write_1(intel_dp,
- DP_LINK_BW_SET,
- intel_dp->link_bw);
-}
-
-int intel_dp_set_lane_count(struct intel_dp *intel_dp)
-{
- printk(BIOS_SPEW, "DP_LANE_COUNT_SET %d ", intel_dp->lane_count);
- return intel_dp_aux_native_write_1(intel_dp,
- DP_LANE_COUNT_SET,
- intel_dp->lane_count);
-}
-
-int intel_dp_set_training_pattern(struct intel_dp *intel_dp,
- u8 pat)
-{
- printk(BIOS_SPEW, "DP_TRAINING_PATTERN_SET");
- return intel_dp_aux_native_write_1(intel_dp,
- DP_TRAINING_PATTERN_SET,
- pat);
-}
-
-int intel_dp_set_training_lane0(struct intel_dp *intel_dp,
- u8 val)
-{
- printk(BIOS_SPEW, "DP_TRAINING_LANE0_SET");
- return intel_dp_aux_native_write_1(intel_dp,
- DP_TRAINING_LANE0_SET,
- val);
-}
-
-/* read bytes from a native aux channel */
-static int
-intel_dp_aux_native_read(struct intel_dp *intel_dp,
- uint16_t address, uint8_t *recv, int recv_bytes)
-{
- uint8_t msg[4];
- int msg_bytes;
- uint8_t reply[20];
- int reply_bytes;
- uint8_t ack;
- int ret;
-
- msg[0] = AUX_NATIVE_READ << 4;
- msg[1] = address >> 8;
- msg[2] = address & 0xff;
- msg[3] = recv_bytes - 1;
-
- msg_bytes = 4;
- reply_bytes = recv_bytes + 1;
-
- for (;;) {
- ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes,
- reply, reply_bytes);
- if (ret == 0)
- return -1;
- if (ret < 0)
- return ret;
- ack = reply[0];
- if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
- memcpy(recv, reply + 1, ret - 1);
- return ret - 1;
- }
- else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
- udelay(100);
- else
- return -1;
- }
-}
-
-int
-intel_dp_i2c_aux_ch(struct intel_dp *intel_dp,
- int mode, uint8_t write_byte, uint8_t *read_byte)
-{
- uint8_t msg[5];
- uint8_t reply[2];
- unsigned retry;
- int msg_bytes;
- int reply_bytes;
- int ret;
-
- /* Set up the command byte */
- if (mode & MODE_I2C_READ)
- msg[0] = AUX_I2C_READ << 4;
- else
- msg[0] = AUX_I2C_WRITE << 4;
-
- if (!(mode & MODE_I2C_STOP))
- msg[0] |= AUX_I2C_MOT << 4;
-
- msg[1] = intel_dp->address >> 8;
- msg[2] = intel_dp->address;
-
- switch (mode) {
- case MODE_I2C_WRITE:
- msg[3] = 0;
- msg[4] = write_byte;
- msg_bytes = 5;
- reply_bytes = 1;
- break;
- case MODE_I2C_READ:
- msg[3] = 0;
- msg_bytes = 4;
- reply_bytes = 2;
- break;
- default:
- msg_bytes = 3;
- reply_bytes = 1;
- break;
- }
-
- for (retry = 0; retry < 5; retry++) {
- ret = intel_dp_aux_ch(intel_dp,
- msg, msg_bytes,
- reply, reply_bytes);
- if (ret < 0) {
- printk(BIOS_ERR, "aux_ch failed %d\n", ret);
- return ret;
- }
-
- switch (reply[0] & AUX_NATIVE_REPLY_MASK) {
- case AUX_NATIVE_REPLY_ACK:
- /* I2C-over-AUX Reply field is only valid
- * when paired with AUX ACK.
- */
- break;
- case AUX_NATIVE_REPLY_NACK:
- printk(BIOS_ERR, "aux_ch native nack\n");
- return -1;
- case AUX_NATIVE_REPLY_DEFER:
- udelay(100);
- continue;
- default:
- printk(BIOS_ERR, "aux_ch invalid native reply 0x%02x\n",
- reply[0]);
- return -1;
- }
-
- switch (reply[0] & AUX_I2C_REPLY_MASK) {
- case AUX_I2C_REPLY_ACK:
- if (mode == MODE_I2C_READ) {
- *read_byte = reply[1];
- }
- return reply_bytes - 1;
- case AUX_I2C_REPLY_NACK:
- printk(BIOS_ERR, "aux_i2c nack\n");
- return -1;
- case AUX_I2C_REPLY_DEFER:
- printk(BIOS_ERR, "aux_i2c defer\n");
- udelay(100);
- break;
- default:
- printk(BIOS_ERR,
- "aux_i2c invalid reply 0x%02x\n", reply[0]);
- return -1;
- }
- }
-
- printk(BIOS_ERR, "too many retries, giving up\n");
- return -1;
-}
-
-int intel_dp_i2c_write(struct intel_dp *intel_dp,
- u8 val)
-{
- return intel_dp_i2c_aux_ch(intel_dp,
- MODE_I2C_WRITE,
- val,
- NULL);
-}
-
-int intel_dp_i2c_read(struct intel_dp *intel_dp,
- u8 *val)
-{
- return intel_dp_i2c_aux_ch(intel_dp,
- MODE_I2C_READ,
- 0,
- val);
-}
-
-int
-intel_dp_i2c_init(struct intel_dp *intel_dp)
-{
- int ret = 0;
-
- /* not clear what we need to do here, if anything.
- * this function was more about setting up the kernel.
- * it's a handy placeholder, so we leave it in for now.
- */
- return ret;
-}
-
-static void
-intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)
-{
- while (*num > DATA_LINK_M_N_MASK || *den > DATA_LINK_M_N_MASK) {
- *num >>= 1;
- *den >>= 1;
- }
-}
-
-unsigned int roundup_power_of_two(unsigned int n);
-
-unsigned int roundup_power_of_two(unsigned int n)
-{
- n--;
- n |= n >> 1;
- n |= n >> 2;
- n |= n >> 4;
- n |= n >> 8;
- n |= n >> 16;
- n++;
- return n;
-}
-
-static void compute_m_n(unsigned int m, unsigned int n,
- unsigned int *ret_m, unsigned int *ret_n)
-{
- /* We noticed in the IO operations that
- * the VBIOS was setting N to DATA_LINK_N_MAX.
- * This makes sense, actually: the bigger N is, i.e.
- * the bigger the denominator is, the bigger
- * the numerator can be, and the more
- * bits of numerator you get, the better the result.
- * So, first pick the max of the two powers of two.
- * And, in the (unlikely) event that you end up with
- * something bigger than DATA_LINK_N_MAX, catch that
- * case with a MIN. Note the second case is unlikely,
- * but we are best off being careful.
- */
- /*
- * This code is incorrect and will always set ret_n
- * to DATA_LINK_N_MAX.
- */
- *ret_n = MAX(roundup_power_of_two(n), DATA_LINK_N_MAX);
- *ret_n = MIN(*ret_n, DATA_LINK_N_MAX);
- *ret_m = ( (unsigned long long)m * *ret_n) / n;
- intel_reduce_m_n_ratio(ret_m, ret_n);
-}
-
-void intel_dp_compute_m_n(unsigned int bits_per_pixel,
- unsigned int nlanes,
- unsigned int pixel_clock,
- unsigned int link_clock,
- struct intel_dp_m_n *m_n)
-{
- m_n->tu = 64;
- compute_m_n(bits_per_pixel * pixel_clock,
- link_clock * nlanes * 8,
- &m_n->gmch_m, &m_n->gmch_n);
-
- compute_m_n(pixel_clock, link_clock,
- &m_n->link_m, &m_n->link_n);
-}
-
-static void ironlake_edp_pll_off(void);
-
-void
-intel_dp_mode_set(struct intel_dp *intel_dp)
-{
- /* Turn on the eDP PLL if needed */
- if (is_edp(intel_dp)) {
- if (!is_pch_edp(intel_dp))
- ironlake_edp_pll_on();
- else
- ironlake_edp_pll_off();
- }
-
- /*
- * There are four kinds of DP registers:
- *
- * IBX PCH
- * SNB CPU
- * IVB CPU
- * CPT PCH
- *
- * IBX PCH and CPU are the same for almost everything,
- * except that the CPU DP PLL is configured in this
- * register
- *
- * CPT PCH is quite different, having many bits moved
- * to the TRANS_DP_CTL register instead. That
- * configuration happens (oddly) in ironlake_pch_enable
- */
-
- /* Preserve the BIOS-computed detected bit. This is
- * supposed to be read-only.
- */
- intel_dp->DP = gtt_read(intel_dp->output_reg) & DP_DETECTED;
- printk(BIOS_SPEW, "%s: initial value is %08lx\n", __func__,
- (unsigned long)intel_dp->DP);
- /* | 0 essentially */
- intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
-
- /* Handle DP bits in common between all three register formats */
-
- switch (intel_dp->lane_count) {
- case 1:
- intel_dp->DP |= DP_PORT_WIDTH_1;
- break;
- case 2:
- intel_dp->DP |= DP_PORT_WIDTH_2;
- break;
- case 4:
- intel_dp->DP |= DP_PORT_WIDTH_4;
- break;
- }
- memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
- intel_dp->link_configuration[0] = intel_dp->link_bw;
- intel_dp->link_configuration[1] = intel_dp->lane_count;
- intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
- /*
- * Check for DPCD version > 1.1 and enhanced framing support
- */
- if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
- (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
- intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
- }
-
- /* Split out the IBX/CPU vs CPT settings */
-
- if (is_cpu_edp(intel_dp) && (intel_dp->gen == 7)) {
- /* what are these? We're not sure.
- if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
- intel_dp->DP |= DP_SYNC_HS_HIGH;
-
- if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
- */
- intel_dp->DP |= DP_SYNC_VS_HIGH;
- /* */
- intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
-
- if (intel_dp->link_configuration[1] &
- DP_LANE_COUNT_ENHANCED_FRAME_EN)
- intel_dp->DP |= DP_ENHANCED_FRAMING;
-
- intel_dp->DP |= intel_dp->pipe << 29;
-
- /* don't miss out required setting for eDP */
- intel_dp->DP |= DP_PLL_ENABLE;
- if (intel_dp->clock < 200000)
- intel_dp->DP |= DP_PLL_FREQ_160MHZ;
- else
- intel_dp->DP |= DP_PLL_FREQ_270MHZ;
- } else if (!intel_dp->has_pch_cpt || is_cpu_edp(intel_dp)) {
- intel_dp->DP |= intel_dp->color_range;
- intel_dp->DP |= DP_LINK_TRAIN_OFF;
-
- if (intel_dp->link_configuration[1] &
- DP_LANE_COUNT_ENHANCED_FRAME_EN)
- intel_dp->DP |= DP_ENHANCED_FRAMING;
-
- if (intel_dp->pipe == 1)
- intel_dp->DP |= DP_PIPEB_SELECT;
-
- if (is_cpu_edp(intel_dp)) {
- /* don't miss out required setting for eDP */
- intel_dp->DP |= DP_PLL_ENABLE;
- if (intel_dp->clock < 200000)
- intel_dp->DP |= DP_PLL_FREQ_160MHZ;
- else
- intel_dp->DP |= DP_PLL_FREQ_270MHZ;
- }
- } else {
- intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
- }
-}
-
-#define IDLE_ON_MASK (PP_ON | 0 | PP_SEQUENCE_MASK | 0 | PP_SEQUENCE_STATE_MASK)
-#define IDLE_ON_VALUE (PP_ON | 0 | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_ON_IDLE)
-
-#define IDLE_OFF_MASK (PP_ON | 0 | PP_SEQUENCE_MASK | 0 | PP_SEQUENCE_STATE_MASK)
-#define IDLE_OFF_VALUE (0 | 0 | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_OFF_IDLE)
-
-#define IDLE_CYCLE_MASK (PP_ON | 0 | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
-#define IDLE_CYCLE_VALUE (0 | 0 | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_OFF_IDLE)
-
-static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
- u32 mask,
- u32 value)
-{
- int i;
- u32 status;
- printk(BIOS_ERR, "[000000.0] [drm:%s], ", __func__);
- printk(BIOS_ERR, "mask %08lx value %08lx status %08lx control %08lx\n",
- (unsigned long) mask, (unsigned long) value,
- (unsigned long)gtt_read(PCH_PP_STATUS),
- (unsigned long)gtt_read(PCH_PP_CONTROL));
-
- for (i = 0, status = gtt_read(PCH_PP_STATUS); ((status & mask) != value) && (i < 5000);
- status = gtt_read(PCH_PP_STATUS)){
- udelay(10);
- }
- if (i > 5000){
- printk(BIOS_ERR,
- "Panel status timeout: status %08lx control %08lx\n",
- (unsigned long)gtt_read(PCH_PP_STATUS),
- (unsigned long)gtt_read(PCH_PP_CONTROL));
- }
-}
-
-static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
-{
- printk(BIOS_ERR, "Wait for panel power on\n");
- ironlake_wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
-}
-
-static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
-{
- printk(BIOS_ERR, "Wait for panel power off time\n");
- ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
-}
-
-static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp)
-{
- printk(BIOS_ERR, "Wait for panel power cycle\n");
- ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
-}
-
-void intel_dp_wait_reg(unsigned long addr,
- unsigned long val)
-{
- unsigned long newval;
- int tries = 0;
-
- while ((newval = gtt_read(addr)) != val) {
- udelay(1);
- if (tries++ > 1000) {
- printk(BIOS_ERR, "%s: Waiting on %08lx to be %08lx, got %08lx\n",
- __func__, addr, val, newval);
- break;
- }
- }
-}
-
-void intel_dp_wait_panel_power_control(unsigned long val)
-{
- intel_dp_wait_reg(PCH_PP_CONTROL, val);
-}
-
-/* Read the current pp_control value, unlocking the register if it
- * is locked
- */
-
-static u32 ironlake_get_pp_control(void)
-{
- u32 control = gtt_read(PCH_PP_CONTROL);
-
- control &= ~PANEL_UNLOCK_MASK;
- control |= PANEL_UNLOCK_REGS;
- return control;
-}
-
-void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
-{
- u32 pp;
-
- if (!is_edp(intel_dp))
- return;
- printk(BIOS_ERR, "Turn eDP VDD on\n");
-
- if (intel_dp->want_panel_vdd) {
- printk(BIOS_ERR, "eDP VDD already requested on\n");
- }
-
- intel_dp->want_panel_vdd = 1;
-
- if (ironlake_edp_have_panel_vdd(intel_dp)) {
- printk(BIOS_ERR, "eDP VDD already on\n");
- return;
- }
-
- if (!ironlake_edp_have_panel_power(intel_dp))
- ironlake_wait_panel_power_cycle(intel_dp);
-
- pp = ironlake_get_pp_control();
- pp |= EDP_FORCE_VDD;
- gtt_write(PCH_PP_CONTROL,pp);
- // remember this if we need it later. Not sure yet.
- ////POSTING_READ(PCH_PP_CONTROL);
- printk(BIOS_ERR, "PCH_PP_STATUS: 0x%08lx PCH_PP_CONTROL: 0x%08lx\n",
- (unsigned long) gtt_read(PCH_PP_STATUS),
- (unsigned long) gtt_read(PCH_PP_CONTROL));
-
- /*
- * If the panel wasn't on, delay before accessing aux channel
- */
- if (!ironlake_edp_have_panel_power(intel_dp)) {
- printk(BIOS_ERR, "eDP was not running\n");
- mdelay(intel_dp->panel_power_up_delay);
- }
-}
-
-static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
-{
- u32 pp;
-
- if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) {
- pp = ironlake_get_pp_control();
- pp &= ~EDP_FORCE_VDD;
- gtt_write(PCH_PP_CONTROL,pp);
- ////POSTING_READ(PCH_PP_CONTROL);
-
- /* Make sure sequencer is idle before allowing subsequent activity */
- printk(BIOS_ERR, "PCH_PP_STATUS: 0x%08lx PCH_PP_CONTROL: 0x%08lx\n",
- (unsigned long) gtt_read(PCH_PP_STATUS),
- (unsigned long) gtt_read(PCH_PP_CONTROL));
-
- mdelay(intel_dp->panel_power_down_delay);
- }
-}
-
-void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, int sync)
-{
- if (!is_edp(intel_dp))
- return;
-
- printk(BIOS_ERR, "Turn eDP VDD off %d\n", intel_dp->want_panel_vdd);
- if (!intel_dp->want_panel_vdd) {
- printk(BIOS_ERR, "eDP VDD not forced on");
- }
-
- intel_dp->want_panel_vdd = 0;
-
- if (sync)
- ironlake_panel_vdd_off_sync(intel_dp);
-}
-
-void ironlake_edp_panel_on(struct intel_dp *intel_dp)
-{
- u32 pp;
-
- if (!is_edp(intel_dp))
- return;
-
- printk(BIOS_ERR, "Turn eDP power on\n");
-
- if (ironlake_edp_have_panel_power(intel_dp)) {
- printk(BIOS_ERR, "eDP power already on\n");
- return;
- }
-
- ironlake_wait_panel_power_cycle(intel_dp);
-
- pp = ironlake_get_pp_control();
- if (intel_dp->gen == 5) {
- /* ILK workaround: disable reset around power sequence */
- pp &= ~PANEL_POWER_RESET;
- gtt_write(PCH_PP_CONTROL,pp);
- ////POSTING_READ(PCH_PP_CONTROL);
- }
-
- pp |= POWER_TARGET_ON;
- if (!(intel_dp->gen == 5))
- pp |= PANEL_POWER_RESET;
-
- gtt_write(PCH_PP_CONTROL,pp);
- ////POSTING_READ(PCH_PP_CONTROL);
-
- ironlake_wait_panel_on(intel_dp);
-
- if (intel_dp->gen == 5) {
- pp |= PANEL_POWER_RESET; /* restore panel reset bit */
- gtt_write(PCH_PP_CONTROL,pp);
- ////POSTING_READ(PCH_PP_CONTROL);
- }
-}
-
-void ironlake_edp_panel_off(struct intel_dp *intel_dp)
-{
- u32 pp;
-
- if (!is_edp(intel_dp))
- return;
-
- printk(BIOS_ERR, "Turn eDP power off\n");
-
- if (intel_dp->want_panel_vdd) {
- printk(BIOS_ERR, "Cannot turn power off while VDD is on\n");
- }
-
- pp = ironlake_get_pp_control();
- pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD |
- PANEL_POWER_RESET | EDP_BLC_ENABLE);
- gtt_write(PCH_PP_CONTROL,pp);
- ////POSTING_READ(PCH_PP_CONTROL);
-
- ironlake_wait_panel_off(intel_dp);
-}
-
-void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
-{
- u32 pp;
-
- if (!is_edp(intel_dp))
- return;
-
- /*
- * If we enable the backlight right away following a panel power
- * on, we may see slight flicker as the panel syncs with the eDP
- * link. So delay a bit to make sure the image is solid before
- * allowing it to appear.
- */
- mdelay(intel_dp->backlight_on_delay);
- pp = ironlake_get_pp_control();
- pp |= EDP_BLC_ENABLE;
- gtt_write(PCH_PP_CONTROL,pp);
- ////POSTING_READ(PCH_PP_CONTROL);
-}
-
-void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
-{
- u32 pp;
-
- if (!is_edp(intel_dp))
- return;
-
- pp = ironlake_get_pp_control();
- pp &= ~EDP_BLC_ENABLE;
- gtt_write(PCH_PP_CONTROL,pp);
- ////POSTING_READ(PCH_PP_CONTROL);
- mdelay(intel_dp->backlight_off_delay);
-}
-
-void ironlake_edp_pll_on(void)
-{
- u32 dpa_ctl;
-
- dpa_ctl = gtt_read(DP_A);
- dpa_ctl |= DP_PLL_ENABLE;
- gtt_write(DP_A,dpa_ctl);
- ////POSTING_READ(DP_A);
- udelay(200);
-}
-
-static void ironlake_edp_pll_off(void)
-{
- u32 dpa_ctl;
-
- dpa_ctl = gtt_read(DP_A);
- dpa_ctl &= ~DP_PLL_ENABLE;
- gtt_write(DP_A,dpa_ctl);
- ////POSTING_READ(DP_A);
- udelay(200);
-}
-
-/* If the sink supports it, try to set the power state appropriately */
-void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
-{
- int ret, i;
-
- /* Should have a valid DPCD by this point */
- if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
- return;
-
- /* the convention, for whatever reason, is that mode > 0 means 'off' */
- if (mode) {
- ret = intel_dp_aux_native_write_1(intel_dp, DP_SET_POWER,
- DP_SET_POWER_D3);
- if (ret != 1) {
- printk(BIOS_ERR, "failed to write sink power state\n");
- }
- } else {
- /*
- * When turning on, we need to retry for 1ms to give the sink
- * time to wake up.
- */
- for (i = 0; i < 3; i++) {
- ret = intel_dp_aux_native_write_1(intel_dp,
- DP_SET_POWER,
- DP_SET_POWER_D0);
- if (ret == 1)
- break;
- mdelay(1);
- }
- }
-}
-
-/*
- * Native read with retry for link status and receiver capability reads for
- * cases where the sink may still be asleep.
- */
-static int
-intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address,
- uint8_t *recv, int recv_bytes)
-{
- int ret, i;
-
- /*
- * Sinks are *supposed* to come up within 1ms from an off state,
- * but we're also supposed to retry 3 times per the spec.
- */
- for (i = 0; i < 3; i++) {
- ret = intel_dp_aux_native_read(intel_dp, address, recv,
- recv_bytes);
- if (ret == recv_bytes)
- return ret;
- mdelay(1);
- }
-
- return ret;
-}
-
-/*
- * Fetch AUX CH registers 0x202 - 0x207 which contain
- * link status information
- */
-int
-intel_dp_get_link_status(struct intel_dp *intel_dp,
- uint8_t link_status[DP_LINK_STATUS_SIZE])
-{
- int ret, i;
-
- ret = intel_dp_aux_native_read_retry(intel_dp,
- DP_LANE0_1_STATUS,
- link_status,
- DP_LINK_STATUS_SIZE);
-
- printk(BIOS_SPEW, "%s:", __func__);
- for (i = 0; i < /* !!sizeof(link_status) == 4*/
- DP_LINK_STATUS_SIZE; i++)
- printk(BIOS_SPEW, " %02x", link_status[i]);
- printk(BIOS_SPEW, "\n");
- return ret;
-}
-
-static uint8_t
-intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
- int r)
-{
- return link_status[r - DP_LANE0_1_STATUS];
-}
-
-const char *voltage_names[] = {
- "0.4V", "0.6V", "0.8V", "1.2V"
-};
-const char *pre_emph_names[] = {
- "0dB", "3.5dB", "6dB", "9.5dB"
-};
-const char *link_train_names[] = {
- "pattern 1", "pattern 2", "idle", "off"
-};
-
-/*
- * These are source-specific values; current Intel hardware supports
- * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
- */
-
-static uint8_t
-intel_dp_voltage_max(struct intel_dp *intel_dp)
-{
-
- if ((intel_dp->gen == 7) && is_cpu_edp(intel_dp))
- return DP_TRAIN_VOLTAGE_SWING_800;
- else if (intel_dp->has_pch_cpt && !is_cpu_edp(intel_dp))
- return DP_TRAIN_VOLTAGE_SWING_1200;
- else
- return DP_TRAIN_VOLTAGE_SWING_800;
-}
-
-static uint8_t
-intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
-{
-
- if (intel_dp->is_haswell){
- switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
- case DP_TRAIN_VOLTAGE_SWING_400:
- return DP_TRAIN_PRE_EMPHASIS_9_5;
- case DP_TRAIN_VOLTAGE_SWING_600:
- return DP_TRAIN_PRE_EMPHASIS_6;
- case DP_TRAIN_VOLTAGE_SWING_800:
- return DP_TRAIN_PRE_EMPHASIS_3_5;
- case DP_TRAIN_VOLTAGE_SWING_1200:
- default:
- return DP_TRAIN_PRE_EMPHASIS_0;
- }
- } else if ((intel_dp->gen == 7) && is_cpu_edp(intel_dp)) {
- switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
- case DP_TRAIN_VOLTAGE_SWING_400:
- return DP_TRAIN_PRE_EMPHASIS_6;
- case DP_TRAIN_VOLTAGE_SWING_600:
- case DP_TRAIN_VOLTAGE_SWING_800:
- return DP_TRAIN_PRE_EMPHASIS_3_5;
- default:
- return DP_TRAIN_PRE_EMPHASIS_0;
- }
- } else {
- switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
- case DP_TRAIN_VOLTAGE_SWING_400:
- return DP_TRAIN_PRE_EMPHASIS_6;
- case DP_TRAIN_VOLTAGE_SWING_600:
- return DP_TRAIN_PRE_EMPHASIS_6;
- case DP_TRAIN_VOLTAGE_SWING_800:
- return DP_TRAIN_PRE_EMPHASIS_3_5;
- case DP_TRAIN_VOLTAGE_SWING_1200:
- default:
- return DP_TRAIN_PRE_EMPHASIS_0;
- }
- }
-}
-
-static void
-intel_get_adjust_train(struct intel_dp *intel_dp,
- uint8_t link_status[DP_LINK_STATUS_SIZE])
-{
- uint8_t v = 0;
- uint8_t p = 0;
- int lane;
- uint8_t voltage_max;
- uint8_t preemph_max;
-
- for (lane = 0; lane < intel_dp->lane_count; lane++) {
- uint8_t this_v = drm_dp_get_adjust_request_voltage(
- link_status, lane);
- uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(
- link_status, lane);
-
- if (this_v > v)
- v = this_v;
- if (this_p > p)
- p = this_p;
- }
-
- voltage_max = intel_dp_voltage_max(intel_dp);
- if (v >= voltage_max)
- v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
-
- preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
- if (p >= preemph_max)
- p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
- printk(BIOS_SPEW, "%s: set to %s %s%s %s\n",
- __func__,
- voltage_names[v&3], pre_emph_names[p&3],
- v & DP_TRAIN_MAX_SWING_REACHED ? ",max volt swing reached":"",
- p & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED ?
- ", max pre emph reached" : "");
- for (lane = 0; lane < 4; lane++)
- intel_dp->train_set[lane] = v | p;
-}
-
-static uint32_t
-intel_dp_signal_levels(uint8_t train_set)
-{
- uint32_t signal_levels = 0;
-
- switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
- case DP_TRAIN_VOLTAGE_SWING_400:
- default:
- signal_levels |= DP_VOLTAGE_0_4;
- break;
- case DP_TRAIN_VOLTAGE_SWING_600:
- signal_levels |= DP_VOLTAGE_0_6;
- break;
- case DP_TRAIN_VOLTAGE_SWING_800:
- signal_levels |= DP_VOLTAGE_0_8;
- break;
- case DP_TRAIN_VOLTAGE_SWING_1200:
- signal_levels |= DP_VOLTAGE_1_2;
- break;
- }
- switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
- case DP_TRAIN_PRE_EMPHASIS_0:
- default:
- signal_levels |= DP_PRE_EMPHASIS_0;
- break;
- case DP_TRAIN_PRE_EMPHASIS_3_5:
- signal_levels |= DP_PRE_EMPHASIS_3_5;
- break;
- case DP_TRAIN_PRE_EMPHASIS_6:
- signal_levels |= DP_PRE_EMPHASIS_6;
- break;
- case DP_TRAIN_PRE_EMPHASIS_9_5:
- signal_levels |= DP_PRE_EMPHASIS_9_5;
- break;
- }
- return signal_levels;
-}
-
-/* Gen6's DP voltage swing and pre-emphasis control */
-static uint32_t
-intel_gen6_edp_signal_levels(uint8_t train_set)
-{
- int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
- DP_TRAIN_PRE_EMPHASIS_MASK);
- switch (signal_levels) {
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
- return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B;
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return EDP_LINK_TRAIN_400MV_3_5DB_SNB_B;
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6:
- return EDP_LINK_TRAIN_400_600MV_6DB_SNB_B;
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
- case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return EDP_LINK_TRAIN_600_800MV_3_5DB_SNB_B;
- case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
- case DP_TRAIN_VOLTAGE_SWING_1200 | DP_TRAIN_PRE_EMPHASIS_0:
- return EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B;
- default:
- printk(BIOS_ERR, "[000000.0] [drm:%s], ", __func__);
- printk(BIOS_ERR, "Unsupported voltage swing/pre-emphasis level:"
- "0x%x\n", signal_levels);
- return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B;
- }
-}
-
-/* Gen7's DP voltage swing and pre-emphasis control */
-static uint32_t
-intel_gen7_edp_signal_levels(uint8_t train_set)
-{
- int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
- DP_TRAIN_PRE_EMPHASIS_MASK);
- switch (signal_levels) {
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
- return EDP_LINK_TRAIN_400MV_0DB_IVB;
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return EDP_LINK_TRAIN_400MV_3_5DB_IVB;
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
- return EDP_LINK_TRAIN_400MV_6DB_IVB;
-
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
- return EDP_LINK_TRAIN_600MV_0DB_IVB;
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return EDP_LINK_TRAIN_600MV_3_5DB_IVB;
-
- case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
- return EDP_LINK_TRAIN_800MV_0DB_IVB;
- case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return EDP_LINK_TRAIN_800MV_3_5DB_IVB;
-
- default:
- printk(BIOS_ERR, "[000000.0] [drm:%s], ", __func__);
- printk(BIOS_ERR, "Unsupported voltage swing/pre-emphasis level:"
- "0x%x\n", signal_levels);
- return EDP_LINK_TRAIN_500MV_0DB_IVB;
- }
-}
-
-/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */
-static uint32_t
-intel_dp_signal_levels_hsw(uint8_t train_set)
-{
- int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
- DP_TRAIN_PRE_EMPHASIS_MASK);
- switch (signal_levels) {
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
- return DDI_BUF_EMP_400MV_0DB_HSW;
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return DDI_BUF_EMP_400MV_3_5DB_HSW;
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
- return DDI_BUF_EMP_400MV_6DB_HSW;
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_9_5:
- return DDI_BUF_EMP_400MV_9_5DB_HSW;
-
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
- return DDI_BUF_EMP_600MV_0DB_HSW;
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return DDI_BUF_EMP_600MV_3_5DB_HSW;
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6:
- return DDI_BUF_EMP_600MV_6DB_HSW;
-
- case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
- return DDI_BUF_EMP_800MV_0DB_HSW;
- case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return DDI_BUF_EMP_800MV_3_5DB_HSW;
- default:
- printk(BIOS_SPEW,
- "Unsupported voltage swing/pre-emphasis level:"
- "0x%x\n", signal_levels);
- return DDI_BUF_EMP_400MV_0DB_HSW;
- }
-}
-
-
-static uint8_t
-intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
- int lane)
-{
- int s = (lane & 1) * 4;
- uint8_t l = link_status[lane>>1];
-
- return (l >> s) & 0xf;
-}
-
-/* Check for clock recovery is done on all channels */
-static int
-intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE],
- int lane_count)
-{
- int lane;
- uint8_t lane_status;
-
- for (lane = 0; lane < lane_count; lane++) {
- lane_status = intel_get_lane_status(link_status, lane);
- printk(BIOS_SPEW,
- "%s: Lane %d, status %02x\n", __func__,
- lane, lane_status);
- if ((lane_status & DP_LANE_CR_DONE) == 0)
- return 0;
- }
- return 1;
-}
-
-/* Check to see if channel eq is done on all channels */
-#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE| \
- DP_LANE_CHANNEL_EQ_DONE| \
- DP_LANE_SYMBOL_LOCKED)
-int
-intel_channel_eq_ok(struct intel_dp *intel_dp,
- uint8_t link_status[DP_LINK_STATUS_SIZE])
-{
- uint8_t lane_align;
- uint8_t lane_status;
- int lane;
-
- lane_align = intel_dp_link_status(link_status,
- DP_LANE_ALIGN_STATUS_UPDATED);
- if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
- return 0;
- for (lane = 0; lane < intel_dp->lane_count; lane++) {
- lane_status = intel_get_lane_status(link_status, lane);
- if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
- return 0;
- }
- return 1;
-}
-
-static int
-intel_dp_set_link_train(struct intel_dp *intel_dp,
- uint32_t dp_reg_value,
- uint8_t dp_train_pat)
-{
- int ret;
- u32 temp;
- int port = intel_dp->port;
- int i;
-
- printk(BIOS_SPEW, "%s: dp_reg_value %08lx dp_train_pat %02x\n",
- __func__, (unsigned long) dp_reg_value, dp_train_pat);
- if (intel_dp->is_haswell){
- temp = gtt_read(DP_TP_CTL(port));
-
- if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
- temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
- else
- temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
-
- temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
- switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
- case DP_TRAINING_PATTERN_DISABLE:
- temp |= DP_TP_CTL_LINK_TRAIN_IDLE;
- gtt_write(DP_TP_CTL(port), temp);
-
- for (i = 0; i < 10; i++){
- u32 status;
- status = gtt_read(DP_TP_STATUS(port));
- if (status & DP_TP_STATUS_IDLE_DONE)
- break;
- }
-
- if (i == 10)
- printk(BIOS_ERR,
- "Timed out waiting for DP idle patterns\n");
-
- temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
- temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
-
- break;
- case DP_TRAINING_PATTERN_1:
- temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
- break;
- case DP_TRAINING_PATTERN_2:
- temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
- break;
- case DP_TRAINING_PATTERN_3:
- temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
- break;
- }
- gtt_write(DP_TP_CTL(port), temp);
-
- } else if (intel_dp->has_pch_cpt &&
- (intel_dp->gen != 7 || !is_cpu_edp(intel_dp))) {
- dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT;
-
- switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
- case DP_TRAINING_PATTERN_DISABLE:
- dp_reg_value |= DP_LINK_TRAIN_OFF_CPT;
- break;
- case DP_TRAINING_PATTERN_1:
- dp_reg_value |= DP_LINK_TRAIN_PAT_1_CPT;
- break;
- case DP_TRAINING_PATTERN_2:
- dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT;
- break;
- case DP_TRAINING_PATTERN_3:
- printk(BIOS_ERR,
- "DP training pattern 3 not supported\n");
- dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT;
- break;
- }
-
- } else {
- dp_reg_value &= ~DP_LINK_TRAIN_MASK;
-
- switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
- case DP_TRAINING_PATTERN_DISABLE:
- dp_reg_value |= DP_LINK_TRAIN_OFF;
- break;
- case DP_TRAINING_PATTERN_1:
- dp_reg_value |= DP_LINK_TRAIN_PAT_1;
- break;
- case DP_TRAINING_PATTERN_2:
- dp_reg_value |= DP_LINK_TRAIN_PAT_2;
- break;
- case DP_TRAINING_PATTERN_3:
- printk(BIOS_ERR,"DP training pattern 3 not supported\n");
- dp_reg_value |= DP_LINK_TRAIN_PAT_2;
- break;
- }
- }
-
- gtt_write(intel_dp->output_reg, dp_reg_value);
- //POSTING_READ(intel_dp->output_reg);
-
- intel_dp_aux_native_write_1(intel_dp,
- DP_TRAINING_PATTERN_SET,
- dp_train_pat);
-
- if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) !=
- DP_TRAINING_PATTERN_DISABLE) {
- ret = intel_dp_aux_native_write(intel_dp,
- DP_TRAINING_LANE0_SET,
- intel_dp->train_set,
- intel_dp->lane_count);
- if (ret != intel_dp->lane_count){
- printk(BIOS_ERR, "%s: wanted %d, got %d\n", __func__,
- intel_dp->lane_count, ret);
- return 0;
- }
- }
-
- printk(BIOS_SPEW, "%s: success\n", __func__);
- return 1;
-}
-
-/* Enable corresponding port and start training pattern 1 */
-void
-intel_dp_start_link_train(struct intel_dp *intel_dp)
-{
- int i;
- uint8_t voltage;
- int clock_recovery = 0;
- int voltage_tries, loop_tries;
- u32 reg;
- uint32_t DP = intel_dp->DP;
-
- if (intel_dp->is_haswell)
- intel_ddi_prepare_link_retrain(intel_dp, intel_dp->port);
-
- /* Write the link configuration data */
- printk(BIOS_SPEW, "Write the link configuration data\n");
- intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
- intel_dp->link_configuration,
- DP_LINK_CONFIGURATION_SIZE);
- printk(BIOS_SPEW, "Written\n");
-
- DP |= DP_PORT_EN;
-
- memset(intel_dp->train_set, 0, 4);
- voltage = 0xff;
- voltage_tries = 0;
- loop_tries = 0;
- clock_recovery = 0;
-
- for (;;) {
- /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
- uint8_t link_status[DP_LINK_STATUS_SIZE];
- uint32_t signal_levels;
-
- if (intel_dp->is_haswell){
- signal_levels =
- intel_dp_signal_levels_hsw(intel_dp->train_set[0]);
- DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels;
- printk(BIOS_SPEW, "Haswell: levels %08x DP %08x\n", signal_levels, DP);
- } else if ((intel_dp->gen == 7) && is_cpu_edp(intel_dp)) {
- signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
- DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
- } else if ((intel_dp->gen == 6) && is_cpu_edp(intel_dp)) {
- signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
- DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
- } else {
- signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
- DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
- }
- printk(BIOS_ERR, "training pattern 1 signal levels %08x\n", signal_levels);
-
- if (intel_dp->has_pch_cpt && ((intel_dp->gen == 7) || !is_cpu_edp(intel_dp)))
- reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
- else
- reg = DP | DP_LINK_TRAIN_PAT_1;
-
- if (!intel_dp_set_link_train(intel_dp, reg,
- DP_TRAINING_PATTERN_1 |
- DP_LINK_SCRAMBLING_DISABLE))
- break;
- /* Set training pattern 1 */
-
- udelay(100);
- if (!intel_dp_get_link_status(intel_dp, link_status)) {
- printk(BIOS_ERR, "failed to get link status\n");
- break;
- }
-
- if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
- printk(BIOS_ERR, "clock recovery OK\n");
- clock_recovery = 1;
- break;
- }
-
- /* Check to see if we've tried the max voltage */
- for (i = 0; i < intel_dp->lane_count; i++)
- if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
- break;
- if (i == intel_dp->lane_count) {
- ++loop_tries;
- if (loop_tries == 5) {
- printk(BIOS_ERR, "too many full retries, give up\n");
- break;
- }
- printk(BIOS_SPEW, "%s: reset train set\n", __func__);
- memset(intel_dp->train_set, 0, 4);
- voltage_tries = 0;
- continue;
- }
-
- /* Check to see if we've tried the same voltage 5 times */
- if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
- ++voltage_tries;
- if (voltage_tries == 5) {
- printk(BIOS_ERR, "too many voltage retries, give up\n");
- break;
- }
- } else
- voltage_tries = 0;
- voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
- printk(BIOS_SPEW, "%s: voltage now %s\n", __func__,
- voltage_names[voltage]);
-
- /* Compute new intel_dp->train_set as requested by target */
- intel_get_adjust_train(intel_dp, link_status);
- printk(BIOS_SPEW, "%s: new intel train set is "
- "%02x%02x%02x%02x",
- __func__,
- intel_dp->train_set[0], intel_dp->train_set[1],
- intel_dp->train_set[2], intel_dp->train_set[3]);
- }
-
- intel_dp->DP = DP;
-}
-
-int
-intel_dp_get_dpcd(struct intel_dp *intel_dp)
-{
- int got = 0, want = sizeof(intel_dp->dpcd), rev;
- got = intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
- want);
- if (got < want) {
- printk(BIOS_SPEW, "%s: got %d, wanted %d\n", __func__, got, want);
- return 0;
- }
-
- rev = intel_dp->dpcd[DP_DPCD_REV];
- if (!rev){
- printk(BIOS_SPEW, "%s: intel->dp[DP_DPCD_REV] is 0\n",
- __func__);
- return 0;
- }
-
- printk(BIOS_SPEW, "DPCD: %02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\n",
- intel_dp->dpcd[0], intel_dp->dpcd[1], intel_dp->dpcd[2],
- intel_dp->dpcd[3], intel_dp->dpcd[4], intel_dp->dpcd[5],
- intel_dp->dpcd[6], intel_dp->dpcd[7]);
- return 1;
-}
-
-/* I have no idea how big max downspread is. 1 byte? Hard as hell to find. */
-int
-intel_dp_get_max_downspread(struct intel_dp *intel_dp, u8 *max_downspread)
-{
- int got, want = 1;
- got = intel_dp_aux_native_read_retry(intel_dp, DP_MAX_DOWNSPREAD, max_downspread,
- want);
- if (got < want) {
- printk(BIOS_SPEW, "%s: got %d, wanted %d\n", __func__, got, want);
- return 0;
- }
-
- printk(BIOS_SPEW, "%s: max_downspread is %02x\n", __func__, *max_downspread);
- return 1;
-}
-
-void intel_dp_set_m_n_regs(struct intel_dp *dp)
-{
- gtt_write(PIPE_DATA_M1(dp->transcoder),
- TU_SIZE(dp->m_n.tu) | dp->m_n.gmch_m);
- gtt_write(PIPE_DATA_N1(dp->transcoder),dp->m_n.gmch_n);
- gtt_write(PIPE_LINK_M1(dp->transcoder),dp->m_n.link_m);
- gtt_write(PIPE_LINK_N1(dp->transcoder),dp->m_n.link_n);
-}
-
-int intel_dp_bw_code_to_link_rate(u8 link_bw)
-{
- switch (link_bw) {
- default:
- printk(BIOS_ERR,
- "ERROR: link_bw(%d) is bogus; must be one of 6, 0xa, or 0x14\n",
- link_bw);
- case DP_LINK_BW_1_62:
- return 162000;
- case DP_LINK_BW_2_7:
- return 270000;
- case DP_LINK_BW_5_4:
- return 540000;
- }
-}
-
-void intel_dp_set_resolution(struct intel_dp *intel_dp)
-{
- gtt_write(HTOTAL(intel_dp->transcoder),intel_dp->htotal);
- gtt_write(HBLANK(intel_dp->transcoder),intel_dp->hblank);
- gtt_write(HSYNC(intel_dp->transcoder),intel_dp->hsync);
- gtt_write(VTOTAL(intel_dp->transcoder),intel_dp->vtotal);
- gtt_write(VBLANK(intel_dp->transcoder),intel_dp->vblank);
- gtt_write(VSYNC(intel_dp->transcoder),intel_dp->vsync);
-}
-
-int intel_dp_get_training_pattern(struct intel_dp *intel_dp,
- u8 *recv)
-{
- return intel_dp_aux_native_read_retry(intel_dp,
- DP_TRAINING_PATTERN_SET,
- recv,
- 0);
-}
-
-int intel_dp_get_lane_count(struct intel_dp *intel_dp,
- u8 *recv)
-{
- int val = intel_dp_aux_native_read_retry(intel_dp,
- DP_LANE_COUNT_SET,
- recv,
- 0);
- *recv &= DP_LANE_COUNT_MASK;
- printk(BIOS_SPEW, "Lane count %s:%d\n", val < 0 ? "fail" : "ok", *recv);
- return val;
-}
-
-int intel_dp_get_lane_align_status(struct intel_dp *intel_dp,
- u8 *recv)
-{
- return intel_dp_aux_native_read_retry(intel_dp,
- DP_LANE_ALIGN_STATUS_UPDATED,
- recv,
- 0);
-}