|
@@ -34,6 +34,8 @@
|
|
|
|
|
|
#include "drm_crtc_helper.h"
|
|
|
|
|
|
+#define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
|
|
|
+
|
|
|
bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
|
|
|
static void intel_update_watermarks(struct drm_device *dev);
|
|
|
|
|
@@ -601,6 +603,23 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+struct drm_connector *
|
|
|
+intel_pipe_get_output (struct drm_crtc *crtc)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
+ struct drm_connector *l_entry, *ret = NULL;
|
|
|
+
|
|
|
+ list_for_each_entry(l_entry, &mode_config->connector_list, head) {
|
|
|
+ if (l_entry->encoder &&
|
|
|
+ l_entry->encoder->crtc == crtc) {
|
|
|
+ ret = l_entry;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
#define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0)
|
|
|
/**
|
|
|
* Returns whether the given set of divisors are valid for a given refclk with
|
|
@@ -790,6 +809,10 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|
|
int err_most = 47;
|
|
|
found = false;
|
|
|
|
|
|
+ /* eDP has only 2 clock choice, no n/m/p setting */
|
|
|
+ if (HAS_eDP)
|
|
|
+ return true;
|
|
|
+
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
|
|
|
return intel_find_pll_igdng_dp(limit, crtc, target,
|
|
|
refclk, best_clock);
|
|
@@ -1052,6 +1075,67 @@ static void i915_disable_vga (struct drm_device *dev)
|
|
|
I915_WRITE(vga_reg, VGA_DISP_DISABLE);
|
|
|
}
|
|
|
|
|
|
+static void igdng_disable_pll_edp (struct drm_crtc *crtc)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ u32 dpa_ctl;
|
|
|
+
|
|
|
+ DRM_DEBUG("\n");
|
|
|
+ dpa_ctl = I915_READ(DP_A);
|
|
|
+ dpa_ctl &= ~DP_PLL_ENABLE;
|
|
|
+ I915_WRITE(DP_A, dpa_ctl);
|
|
|
+}
|
|
|
+
|
|
|
+static void igdng_enable_pll_edp (struct drm_crtc *crtc)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ u32 dpa_ctl;
|
|
|
+
|
|
|
+ dpa_ctl = I915_READ(DP_A);
|
|
|
+ dpa_ctl |= DP_PLL_ENABLE;
|
|
|
+ I915_WRITE(DP_A, dpa_ctl);
|
|
|
+ udelay(200);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void igdng_set_pll_edp (struct drm_crtc *crtc, int clock)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ u32 dpa_ctl;
|
|
|
+
|
|
|
+ DRM_DEBUG("eDP PLL enable for clock %d\n", clock);
|
|
|
+ dpa_ctl = I915_READ(DP_A);
|
|
|
+ dpa_ctl &= ~DP_PLL_FREQ_MASK;
|
|
|
+
|
|
|
+ if (clock < 200000) {
|
|
|
+ u32 temp;
|
|
|
+ dpa_ctl |= DP_PLL_FREQ_160MHZ;
|
|
|
+ /* workaround for 160Mhz:
|
|
|
+ 1) program 0x4600c bits 15:0 = 0x8124
|
|
|
+ 2) program 0x46010 bit 0 = 1
|
|
|
+ 3) program 0x46034 bit 24 = 1
|
|
|
+ 4) program 0x64000 bit 14 = 1
|
|
|
+ */
|
|
|
+ temp = I915_READ(0x4600c);
|
|
|
+ temp &= 0xffff0000;
|
|
|
+ I915_WRITE(0x4600c, temp | 0x8124);
|
|
|
+
|
|
|
+ temp = I915_READ(0x46010);
|
|
|
+ I915_WRITE(0x46010, temp | 1);
|
|
|
+
|
|
|
+ temp = I915_READ(0x46034);
|
|
|
+ I915_WRITE(0x46034, temp | (1 << 24));
|
|
|
+ } else {
|
|
|
+ dpa_ctl |= DP_PLL_FREQ_270MHZ;
|
|
|
+ }
|
|
|
+ I915_WRITE(DP_A, dpa_ctl);
|
|
|
+
|
|
|
+ udelay(500);
|
|
|
+}
|
|
|
+
|
|
|
static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
@@ -1093,27 +1177,32 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
|
case DRM_MODE_DPMS_STANDBY:
|
|
|
case DRM_MODE_DPMS_SUSPEND:
|
|
|
DRM_DEBUG("crtc %d dpms on\n", pipe);
|
|
|
- /* enable PCH DPLL */
|
|
|
- temp = I915_READ(pch_dpll_reg);
|
|
|
- if ((temp & DPLL_VCO_ENABLE) == 0) {
|
|
|
- I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
|
|
|
- I915_READ(pch_dpll_reg);
|
|
|
- }
|
|
|
-
|
|
|
- /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
|
|
|
- temp = I915_READ(fdi_rx_reg);
|
|
|
- I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
|
|
|
- FDI_SEL_PCDCLK |
|
|
|
- FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
|
|
|
- I915_READ(fdi_rx_reg);
|
|
|
- udelay(200);
|
|
|
+ if (HAS_eDP) {
|
|
|
+ /* enable eDP PLL */
|
|
|
+ igdng_enable_pll_edp(crtc);
|
|
|
+ } else {
|
|
|
+ /* enable PCH DPLL */
|
|
|
+ temp = I915_READ(pch_dpll_reg);
|
|
|
+ if ((temp & DPLL_VCO_ENABLE) == 0) {
|
|
|
+ I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
|
|
|
+ I915_READ(pch_dpll_reg);
|
|
|
+ }
|
|
|
|
|
|
- /* Enable CPU FDI TX PLL, always on for IGDNG */
|
|
|
- temp = I915_READ(fdi_tx_reg);
|
|
|
- if ((temp & FDI_TX_PLL_ENABLE) == 0) {
|
|
|
- I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
|
|
|
- I915_READ(fdi_tx_reg);
|
|
|
- udelay(100);
|
|
|
+ /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
|
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
|
+ I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
|
|
|
+ FDI_SEL_PCDCLK |
|
|
|
+ FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
|
|
|
+ I915_READ(fdi_rx_reg);
|
|
|
+ udelay(200);
|
|
|
+
|
|
|
+ /* Enable CPU FDI TX PLL, always on for IGDNG */
|
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
|
+ if ((temp & FDI_TX_PLL_ENABLE) == 0) {
|
|
|
+ I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
|
|
|
+ I915_READ(fdi_tx_reg);
|
|
|
+ udelay(100);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* Enable CPU pipe */
|
|
@@ -1132,122 +1221,126 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
|
I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
|
|
|
}
|
|
|
|
|
|
- /* enable CPU FDI TX and PCH FDI RX */
|
|
|
- temp = I915_READ(fdi_tx_reg);
|
|
|
- temp |= FDI_TX_ENABLE;
|
|
|
- temp |= FDI_DP_PORT_WIDTH_X4; /* default */
|
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
- temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
|
- I915_WRITE(fdi_tx_reg, temp);
|
|
|
- I915_READ(fdi_tx_reg);
|
|
|
+ if (!HAS_eDP) {
|
|
|
+ /* enable CPU FDI TX and PCH FDI RX */
|
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
|
+ temp |= FDI_TX_ENABLE;
|
|
|
+ temp |= FDI_DP_PORT_WIDTH_X4; /* default */
|
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
|
+ I915_WRITE(fdi_tx_reg, temp);
|
|
|
+ I915_READ(fdi_tx_reg);
|
|
|
|
|
|
- temp = I915_READ(fdi_rx_reg);
|
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
- temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
|
- I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE);
|
|
|
- I915_READ(fdi_rx_reg);
|
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
|
+ I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE);
|
|
|
+ I915_READ(fdi_rx_reg);
|
|
|
|
|
|
- udelay(150);
|
|
|
+ udelay(150);
|
|
|
|
|
|
- /* Train FDI. */
|
|
|
- /* umask FDI RX Interrupt symbol_lock and bit_lock bit
|
|
|
- for train result */
|
|
|
- temp = I915_READ(fdi_rx_imr_reg);
|
|
|
- temp &= ~FDI_RX_SYMBOL_LOCK;
|
|
|
- temp &= ~FDI_RX_BIT_LOCK;
|
|
|
- I915_WRITE(fdi_rx_imr_reg, temp);
|
|
|
- I915_READ(fdi_rx_imr_reg);
|
|
|
- udelay(150);
|
|
|
+ /* Train FDI. */
|
|
|
+ /* umask FDI RX Interrupt symbol_lock and bit_lock bit
|
|
|
+ for train result */
|
|
|
+ temp = I915_READ(fdi_rx_imr_reg);
|
|
|
+ temp &= ~FDI_RX_SYMBOL_LOCK;
|
|
|
+ temp &= ~FDI_RX_BIT_LOCK;
|
|
|
+ I915_WRITE(fdi_rx_imr_reg, temp);
|
|
|
+ I915_READ(fdi_rx_imr_reg);
|
|
|
+ udelay(150);
|
|
|
|
|
|
- temp = I915_READ(fdi_rx_iir_reg);
|
|
|
- DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
|
|
+ temp = I915_READ(fdi_rx_iir_reg);
|
|
|
+ DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
|
|
|
|
|
- if ((temp & FDI_RX_BIT_LOCK) == 0) {
|
|
|
- for (j = 0; j < tries; j++) {
|
|
|
- temp = I915_READ(fdi_rx_iir_reg);
|
|
|
- DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
|
|
- if (temp & FDI_RX_BIT_LOCK)
|
|
|
- break;
|
|
|
- udelay(200);
|
|
|
- }
|
|
|
- if (j != tries)
|
|
|
+ if ((temp & FDI_RX_BIT_LOCK) == 0) {
|
|
|
+ for (j = 0; j < tries; j++) {
|
|
|
+ temp = I915_READ(fdi_rx_iir_reg);
|
|
|
+ DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
|
|
+ if (temp & FDI_RX_BIT_LOCK)
|
|
|
+ break;
|
|
|
+ udelay(200);
|
|
|
+ }
|
|
|
+ if (j != tries)
|
|
|
+ I915_WRITE(fdi_rx_iir_reg,
|
|
|
+ temp | FDI_RX_BIT_LOCK);
|
|
|
+ else
|
|
|
+ DRM_DEBUG("train 1 fail\n");
|
|
|
+ } else {
|
|
|
I915_WRITE(fdi_rx_iir_reg,
|
|
|
temp | FDI_RX_BIT_LOCK);
|
|
|
- else
|
|
|
- DRM_DEBUG("train 1 fail\n");
|
|
|
- } else {
|
|
|
- I915_WRITE(fdi_rx_iir_reg,
|
|
|
- temp | FDI_RX_BIT_LOCK);
|
|
|
- DRM_DEBUG("train 1 ok 2!\n");
|
|
|
- }
|
|
|
- temp = I915_READ(fdi_tx_reg);
|
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
- temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
|
- I915_WRITE(fdi_tx_reg, temp);
|
|
|
-
|
|
|
- temp = I915_READ(fdi_rx_reg);
|
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
- temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
|
- I915_WRITE(fdi_rx_reg, temp);
|
|
|
+ DRM_DEBUG("train 1 ok 2!\n");
|
|
|
+ }
|
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
|
+ I915_WRITE(fdi_tx_reg, temp);
|
|
|
+
|
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
|
+ I915_WRITE(fdi_rx_reg, temp);
|
|
|
|
|
|
- udelay(150);
|
|
|
+ udelay(150);
|
|
|
|
|
|
- temp = I915_READ(fdi_rx_iir_reg);
|
|
|
- DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
|
|
+ temp = I915_READ(fdi_rx_iir_reg);
|
|
|
+ DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
|
|
|
|
|
- if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
|
|
|
- for (j = 0; j < tries; j++) {
|
|
|
- temp = I915_READ(fdi_rx_iir_reg);
|
|
|
- DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
|
|
- if (temp & FDI_RX_SYMBOL_LOCK)
|
|
|
- break;
|
|
|
- udelay(200);
|
|
|
- }
|
|
|
- if (j != tries) {
|
|
|
+ if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
|
|
|
+ for (j = 0; j < tries; j++) {
|
|
|
+ temp = I915_READ(fdi_rx_iir_reg);
|
|
|
+ DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
|
|
|
+ if (temp & FDI_RX_SYMBOL_LOCK)
|
|
|
+ break;
|
|
|
+ udelay(200);
|
|
|
+ }
|
|
|
+ if (j != tries) {
|
|
|
+ I915_WRITE(fdi_rx_iir_reg,
|
|
|
+ temp | FDI_RX_SYMBOL_LOCK);
|
|
|
+ DRM_DEBUG("train 2 ok 1!\n");
|
|
|
+ } else
|
|
|
+ DRM_DEBUG("train 2 fail\n");
|
|
|
+ } else {
|
|
|
I915_WRITE(fdi_rx_iir_reg,
|
|
|
temp | FDI_RX_SYMBOL_LOCK);
|
|
|
- DRM_DEBUG("train 2 ok 1!\n");
|
|
|
- } else
|
|
|
- DRM_DEBUG("train 2 fail\n");
|
|
|
- } else {
|
|
|
- I915_WRITE(fdi_rx_iir_reg, temp | FDI_RX_SYMBOL_LOCK);
|
|
|
- DRM_DEBUG("train 2 ok 2!\n");
|
|
|
- }
|
|
|
- DRM_DEBUG("train done\n");
|
|
|
+ DRM_DEBUG("train 2 ok 2!\n");
|
|
|
+ }
|
|
|
+ DRM_DEBUG("train done\n");
|
|
|
|
|
|
- /* set transcoder timing */
|
|
|
- I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg));
|
|
|
- I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg));
|
|
|
- I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg));
|
|
|
+ /* set transcoder timing */
|
|
|
+ I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg));
|
|
|
+ I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg));
|
|
|
+ I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg));
|
|
|
|
|
|
- I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg));
|
|
|
- I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg));
|
|
|
- I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg));
|
|
|
+ I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg));
|
|
|
+ I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg));
|
|
|
+ I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg));
|
|
|
|
|
|
- /* enable PCH transcoder */
|
|
|
- temp = I915_READ(transconf_reg);
|
|
|
- I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
|
|
|
- I915_READ(transconf_reg);
|
|
|
+ /* enable PCH transcoder */
|
|
|
+ temp = I915_READ(transconf_reg);
|
|
|
+ I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
|
|
|
+ I915_READ(transconf_reg);
|
|
|
|
|
|
- while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0)
|
|
|
- ;
|
|
|
+ while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0)
|
|
|
+ ;
|
|
|
|
|
|
- /* enable normal */
|
|
|
+ /* enable normal */
|
|
|
|
|
|
- temp = I915_READ(fdi_tx_reg);
|
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
- I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
|
|
|
- FDI_TX_ENHANCE_FRAME_ENABLE);
|
|
|
- I915_READ(fdi_tx_reg);
|
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
+ I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
|
|
|
+ FDI_TX_ENHANCE_FRAME_ENABLE);
|
|
|
+ I915_READ(fdi_tx_reg);
|
|
|
|
|
|
- temp = I915_READ(fdi_rx_reg);
|
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
- I915_WRITE(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE |
|
|
|
- FDI_RX_ENHANCE_FRAME_ENABLE);
|
|
|
- I915_READ(fdi_rx_reg);
|
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
+ I915_WRITE(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE |
|
|
|
+ FDI_RX_ENHANCE_FRAME_ENABLE);
|
|
|
+ I915_READ(fdi_rx_reg);
|
|
|
|
|
|
- /* wait one idle pattern time */
|
|
|
- udelay(100);
|
|
|
+ /* wait one idle pattern time */
|
|
|
+ udelay(100);
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
intel_crtc_load_lut(crtc);
|
|
|
|
|
@@ -1286,6 +1379,10 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
|
} else
|
|
|
DRM_DEBUG("crtc %d is disabled\n", pipe);
|
|
|
|
|
|
+ if (HAS_eDP) {
|
|
|
+ igdng_disable_pll_edp(crtc);
|
|
|
+ }
|
|
|
+
|
|
|
/* disable CPU FDI tx and PCH FDI rx */
|
|
|
temp = I915_READ(fdi_tx_reg);
|
|
|
I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_ENABLE);
|
|
@@ -2152,6 +2249,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
u32 dpll = 0, fp = 0, dspcntr, pipeconf;
|
|
|
bool ok, is_sdvo = false, is_dvo = false;
|
|
|
bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
|
|
|
+ bool is_edp = false;
|
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
struct drm_connector *connector;
|
|
|
const intel_limit_t *limit;
|
|
@@ -2199,6 +2297,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
case INTEL_OUTPUT_DISPLAYPORT:
|
|
|
is_dp = true;
|
|
|
break;
|
|
|
+ case INTEL_OUTPUT_EDP:
|
|
|
+ is_edp = true;
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
num_outputs++;
|
|
@@ -2251,16 +2352,27 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
|
|
/* FDI link */
|
|
|
if (IS_IGDNG(dev)) {
|
|
|
- /* DP over FDI requires target mode clock
|
|
|
- instead of link clock */
|
|
|
- if (is_dp)
|
|
|
+ int lane, link_bw;
|
|
|
+ /* eDP doesn't require FDI link, so just set DP M/N
|
|
|
+ according to current link config */
|
|
|
+ if (is_edp) {
|
|
|
+ struct drm_connector *edp;
|
|
|
target_clock = mode->clock;
|
|
|
- else
|
|
|
- target_clock = adjusted_mode->clock;
|
|
|
- igdng_compute_m_n(3, 4, /* lane num 4 */
|
|
|
- target_clock,
|
|
|
- 270000, /* lane clock */
|
|
|
- &m_n);
|
|
|
+ edp = intel_pipe_get_output(crtc);
|
|
|
+ intel_edp_link_config(to_intel_output(edp),
|
|
|
+ &lane, &link_bw);
|
|
|
+ } else {
|
|
|
+ /* DP over FDI requires target mode clock
|
|
|
+ instead of link clock */
|
|
|
+ if (is_dp)
|
|
|
+ target_clock = mode->clock;
|
|
|
+ else
|
|
|
+ target_clock = adjusted_mode->clock;
|
|
|
+ lane = 4;
|
|
|
+ link_bw = 270000;
|
|
|
+ }
|
|
|
+ igdng_compute_m_n(3, lane, target_clock,
|
|
|
+ link_bw, &m_n);
|
|
|
}
|
|
|
|
|
|
if (IS_IGD(dev))
|
|
@@ -2382,29 +2494,15 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
dpll_reg = pch_dpll_reg;
|
|
|
}
|
|
|
|
|
|
- if (dpll & DPLL_VCO_ENABLE) {
|
|
|
+ if (is_edp) {
|
|
|
+ igdng_disable_pll_edp(crtc);
|
|
|
+ } else if ((dpll & DPLL_VCO_ENABLE)) {
|
|
|
I915_WRITE(fp_reg, fp);
|
|
|
I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
|
|
|
I915_READ(dpll_reg);
|
|
|
udelay(150);
|
|
|
}
|
|
|
|
|
|
- if (IS_IGDNG(dev)) {
|
|
|
- /* enable PCH clock reference source */
|
|
|
- /* XXX need to change the setting for other outputs */
|
|
|
- u32 temp;
|
|
|
- temp = I915_READ(PCH_DREF_CONTROL);
|
|
|
- temp &= ~DREF_NONSPREAD_SOURCE_MASK;
|
|
|
- temp |= DREF_NONSPREAD_CK505_ENABLE;
|
|
|
- temp &= ~DREF_SSC_SOURCE_MASK;
|
|
|
- temp |= DREF_SSC_SOURCE_ENABLE;
|
|
|
- temp &= ~DREF_SSC1_ENABLE;
|
|
|
- /* if no eDP, disable source output to CPU */
|
|
|
- temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
|
|
- temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
|
|
- I915_WRITE(PCH_DREF_CONTROL, temp);
|
|
|
- }
|
|
|
-
|
|
|
/* The LVDS pin pair needs to be on before the DPLLs are enabled.
|
|
|
* This is an exception to the general rule that mode_set doesn't turn
|
|
|
* things on.
|
|
@@ -2436,23 +2534,25 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
if (is_dp)
|
|
|
intel_dp_set_m_n(crtc, mode, adjusted_mode);
|
|
|
|
|
|
- I915_WRITE(fp_reg, fp);
|
|
|
- I915_WRITE(dpll_reg, dpll);
|
|
|
- I915_READ(dpll_reg);
|
|
|
- /* Wait for the clocks to stabilize. */
|
|
|
- udelay(150);
|
|
|
-
|
|
|
- if (IS_I965G(dev) && !IS_IGDNG(dev)) {
|
|
|
- sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
|
|
|
- I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
|
|
|
- ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
|
|
|
- } else {
|
|
|
- /* write it again -- the BIOS does, after all */
|
|
|
+ if (!is_edp) {
|
|
|
+ I915_WRITE(fp_reg, fp);
|
|
|
I915_WRITE(dpll_reg, dpll);
|
|
|
+ I915_READ(dpll_reg);
|
|
|
+ /* Wait for the clocks to stabilize. */
|
|
|
+ udelay(150);
|
|
|
+
|
|
|
+ if (IS_I965G(dev) && !IS_IGDNG(dev)) {
|
|
|
+ sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
|
|
|
+ I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
|
|
|
+ ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
|
|
|
+ } else {
|
|
|
+ /* write it again -- the BIOS does, after all */
|
|
|
+ I915_WRITE(dpll_reg, dpll);
|
|
|
+ }
|
|
|
+ I915_READ(dpll_reg);
|
|
|
+ /* Wait for the clocks to stabilize. */
|
|
|
+ udelay(150);
|
|
|
}
|
|
|
- I915_READ(dpll_reg);
|
|
|
- /* Wait for the clocks to stabilize. */
|
|
|
- udelay(150);
|
|
|
|
|
|
I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
|
|
|
((adjusted_mode->crtc_htotal - 1) << 16));
|
|
@@ -2482,10 +2582,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
I915_WRITE(link_m1_reg, m_n.link_m);
|
|
|
I915_WRITE(link_n1_reg, m_n.link_n);
|
|
|
|
|
|
- /* enable FDI RX PLL too */
|
|
|
- temp = I915_READ(fdi_rx_reg);
|
|
|
- I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
|
|
|
- udelay(200);
|
|
|
+ if (is_edp) {
|
|
|
+ igdng_set_pll_edp(crtc, adjusted_mode->clock);
|
|
|
+ } else {
|
|
|
+ /* enable FDI RX PLL too */
|
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
|
+ I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
|
|
|
+ udelay(200);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
I915_WRITE(pipeconf_reg, pipeconf);
|
|
@@ -3083,6 +3187,9 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|
|
if (IS_IGDNG(dev)) {
|
|
|
int found;
|
|
|
|
|
|
+ if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
|
|
|
+ intel_dp_init(dev, DP_A);
|
|
|
+
|
|
|
if (I915_READ(HDMIB) & PORT_DETECTED) {
|
|
|
/* check SDVOB */
|
|
|
/* found = intel_sdvo_init(dev, HDMIB); */
|
|
@@ -3179,6 +3286,10 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|
|
(1 << 1));
|
|
|
clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT);
|
|
|
break;
|
|
|
+ case INTEL_OUTPUT_EDP:
|
|
|
+ crtc_mask = (1 << 1);
|
|
|
+ clone_mask = (1 << INTEL_OUTPUT_EDP);
|
|
|
+ break;
|
|
|
}
|
|
|
encoder->possible_crtcs = crtc_mask;
|
|
|
encoder->possible_clones = intel_connector_clones(dev, clone_mask);
|