Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 345202
b: refs/heads/master
c: 01a415f
h: refs/heads/master
v: v3
  • Loading branch information
Daniel Vetter committed Nov 11, 2012
1 parent 3ade5d4 commit 854e36e
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 47fab7370b45c6708e57430831839261d0d63f53
refs/heads/master: 01a415fd026c1a413a7016ee880fff7a113af6c8
5 changes: 3 additions & 2 deletions trunk/drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -3811,8 +3811,9 @@
#define SOUTH_CHICKEN1 0xc2000
#define FDIA_PHASE_SYNC_SHIFT_OVR 19
#define FDIA_PHASE_SYNC_SHIFT_EN 18
#define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2)))
#define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2)))
#define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2)))
#define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2)))
#define FDI_BC_BIFURCATION_SELECT (1 << 12)
#define SOUTH_CHICKEN2 0xc2004
#define DPLS_EDP_PPS_FIX_DIS (1<<0)

Expand Down
122 changes: 118 additions & 4 deletions trunk/drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -2343,6 +2343,29 @@ static void cpt_phase_pointer_enable(struct drm_device *dev, int pipe)
POSTING_READ(SOUTH_CHICKEN1);
}

static void ivb_modeset_global_resources(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *pipe_B_crtc =
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
struct intel_crtc *pipe_C_crtc =
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_C]);
uint32_t temp;

/* When everything is off disable fdi C so that we could enable fdi B
* with all lanes. XXX: This misses the case where a pipe is not using
* any pch resources and so doesn't need any fdi lanes. */
if (!pipe_B_crtc->base.enabled && !pipe_C_crtc->base.enabled) {
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);

temp = I915_READ(SOUTH_CHICKEN1);
temp &= ~FDI_BC_BIFURCATION_SELECT;
DRM_DEBUG_KMS("disabling fdi C rx\n");
I915_WRITE(SOUTH_CHICKEN1, temp);
}
}

/* The FDI link training functions for ILK/Ibexpeak. */
static void ironlake_fdi_link_train(struct drm_crtc *crtc)
{
Expand Down Expand Up @@ -2602,6 +2625,9 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
POSTING_READ(reg);
udelay(150);

DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n",
I915_READ(FDI_RX_IIR(pipe)));

/* enable CPU FDI TX and PCH FDI RX */
reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
Expand Down Expand Up @@ -2648,7 +2674,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
if (temp & FDI_RX_BIT_LOCK ||
(I915_READ(reg) & FDI_RX_BIT_LOCK)) {
I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
DRM_DEBUG_KMS("FDI train 1 done.\n");
DRM_DEBUG_KMS("FDI train 1 done, level %i.\n", i);
break;
}
}
Expand Down Expand Up @@ -2689,7 +2715,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)

if (temp & FDI_RX_SYMBOL_LOCK) {
I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
DRM_DEBUG_KMS("FDI train 2 done.\n");
DRM_DEBUG_KMS("FDI train 2 done, level %i.\n", i);
break;
}
}
Expand Down Expand Up @@ -5013,6 +5039,88 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
return true;
}

static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t temp;

temp = I915_READ(SOUTH_CHICKEN1);
if (temp & FDI_BC_BIFURCATION_SELECT)
return;

WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);

temp |= FDI_BC_BIFURCATION_SELECT;
DRM_DEBUG_KMS("enabling fdi C rx\n");
I915_WRITE(SOUTH_CHICKEN1, temp);
POSTING_READ(SOUTH_CHICKEN1);
}

static bool ironlake_check_fdi_lanes(struct intel_crtc *intel_crtc)
{
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *pipe_B_crtc =
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);

DRM_DEBUG_KMS("checking fdi config on pipe %i, lanes %i\n",
intel_crtc->pipe, intel_crtc->fdi_lanes);
if (intel_crtc->fdi_lanes > 4) {
DRM_DEBUG_KMS("invalid fdi lane config on pipe %i: %i lanes\n",
intel_crtc->pipe, intel_crtc->fdi_lanes);
/* Clamp lanes to avoid programming the hw with bogus values. */
intel_crtc->fdi_lanes = 4;

return false;
}

if (dev_priv->num_pipe == 2)
return true;

switch (intel_crtc->pipe) {
case PIPE_A:
return true;
case PIPE_B:
if (dev_priv->pipe_to_crtc_mapping[PIPE_C]->enabled &&
intel_crtc->fdi_lanes > 2) {
DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %i: %i lanes\n",
intel_crtc->pipe, intel_crtc->fdi_lanes);
/* Clamp lanes to avoid programming the hw with bogus values. */
intel_crtc->fdi_lanes = 2;

return false;
}

if (intel_crtc->fdi_lanes > 2)
WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
else
cpt_enable_fdi_bc_bifurcation(dev);

return true;
case PIPE_C:
if (!pipe_B_crtc->base.enabled || pipe_B_crtc->fdi_lanes <= 2) {
if (intel_crtc->fdi_lanes > 2) {
DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %i: %i lanes\n",
intel_crtc->pipe, intel_crtc->fdi_lanes);
/* Clamp lanes to avoid programming the hw with bogus values. */
intel_crtc->fdi_lanes = 2;

return false;
}
} else {
DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n");
return false;
}

cpt_enable_fdi_bc_bifurcation(dev);

return true;
default:
BUG();
}
}

static void ironlake_set_m_n(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
Expand Down Expand Up @@ -5211,7 +5319,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
struct intel_encoder *encoder;
u32 temp;
int ret;
bool dither;
bool dither, fdi_config_ok;

for_each_encoder_on_crtc(dev, crtc, encoder) {
switch (encoder->type) {
Expand Down Expand Up @@ -5349,8 +5457,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,

intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);

/* Note, this also computes intel_crtc->fdi_lanes which is used below in
* ironlake_check_fdi_lanes. */
ironlake_set_m_n(crtc, mode, adjusted_mode);

fdi_config_ok = ironlake_check_fdi_lanes(intel_crtc);

if (is_cpu_edp)
ironlake_set_pll_edp(crtc, adjusted_mode->clock);

Expand All @@ -5368,7 +5480,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,

intel_update_linetime_watermarks(dev, pipe, adjusted_mode);

return ret;
return fdi_config_ok ? ret : -EINVAL;
}

static int haswell_crtc_mode_set(struct drm_crtc *crtc,
Expand Down Expand Up @@ -8331,6 +8443,8 @@ static void intel_init_display(struct drm_device *dev)
/* FIXME: detect B0+ stepping and use auto training */
dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
dev_priv->display.write_eld = ironlake_write_eld;
dev_priv->display.modeset_global_resources =
ivb_modeset_global_resources;
} else if (IS_HASWELL(dev)) {
dev_priv->display.fdi_link_train = hsw_fdi_link_train;
dev_priv->display.write_eld = haswell_write_eld;
Expand Down

0 comments on commit 854e36e

Please sign in to comment.