Skip to content

Commit

Permalink
drm/i915: Fix frame start delay programming
Browse files Browse the repository at this point in the history
Currently we're blindly poking at the frame start delay bits
in PIPECONF when trying to sanitize the hardware state. Those
bits decided to move elsewhere on HSW, so on many platforms
we're not doing anything at all here. Also we're forgetting
about the PCH transcoder entirely.

Add all the bit definitions for the various homes these bits
have had throughout the years, and reset them all to zero.

However I'm not entirely sure this is a safe thing to do. If
not I guess we'd want full readout+statecheck for this stuff.
For now let's stick to the current logic and hope for the
best.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191024122138.25065-3-ville.syrjala@linux.intel.com
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
  • Loading branch information
Ville Syrjälä committed Nov 15, 2019
1 parent c212fbd commit cc7a4cf
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 19 deletions.
101 changes: 88 additions & 13 deletions drivers/gpu/drm/i915/display/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -1674,11 +1674,16 @@ static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s
assert_fdi_rx_enabled(dev_priv, pipe);

if (HAS_PCH_CPT(dev_priv)) {
/* Workaround: Set the timing override bit before enabling the
* pch transcoder. */
reg = TRANS_CHICKEN2(pipe);
val = I915_READ(reg);
/*
* Workaround: Set the timing override bit
* before enabling the pch transcoder.
*/
val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
/* Configure frame start delay to match the CPU */
val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
I915_WRITE(reg, val);
}

Expand All @@ -1687,6 +1692,10 @@ static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s
pipeconf_val = I915_READ(PIPECONF(pipe));

if (HAS_PCH_IBX(dev_priv)) {
/* Configure frame start delay to match the CPU */
val &= ~TRANS_FRAME_START_DELAY_MASK;
val |= TRANS_FRAME_START_DELAY(0);

/*
* Make the BPC in transcoder be consistent with
* that in pipeconf reg. For HDMI we must use 8bpc
Expand Down Expand Up @@ -1724,9 +1733,12 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
assert_fdi_rx_enabled(dev_priv, PIPE_A);

/* Workaround: set timing override bit. */
val = I915_READ(TRANS_CHICKEN2(PIPE_A));
/* Workaround: set timing override bit. */
val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
/* Configure frame start delay to match the CPU */
val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);

val = TRANS_ENABLE;
Expand Down Expand Up @@ -6583,6 +6595,19 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc)
I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val);
}

static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
i915_reg_t reg = CHICKEN_TRANS(crtc_state->cpu_transcoder);
u32 val;

val = I915_READ(reg);
val &= ~HSW_FRAME_START_DELAY_MASK;
val |= HSW_FRAME_START_DELAY(0);
I915_WRITE(reg, val);
}

static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
struct intel_atomic_state *state)
{
Expand Down Expand Up @@ -6625,8 +6650,10 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
&pipe_config->fdi_m_n, NULL);
}

if (!transcoder_is_dsi(cpu_transcoder))
if (!transcoder_is_dsi(cpu_transcoder)) {
hsw_set_frame_start_delay(pipe_config);
haswell_set_pipeconf(pipe_config);
}

if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
bdw_set_pipemisc(pipe_config);
Expand Down Expand Up @@ -8523,6 +8550,8 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)

pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);

pipeconf |= PIPECONF_FRAME_START_DELAY(0);

I915_WRITE(PIPECONF(crtc->pipe), pipeconf);
POSTING_READ(PIPECONF(crtc->pipe));
}
Expand Down Expand Up @@ -9604,6 +9633,8 @@ static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state)

val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);

val |= PIPECONF_FRAME_START_DELAY(0);

I915_WRITE(PIPECONF(pipe), val);
POSTING_READ(PIPECONF(pipe));
}
Expand Down Expand Up @@ -17202,25 +17233,69 @@ static bool has_pch_trancoder(struct drm_i915_private *dev_priv,
(HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A);
}

static void intel_sanitize_crtc(struct intel_crtc *crtc,
struct drm_modeset_acquire_ctx *ctx)
static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc_state)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;

/* Clear any frame start delays used for debugging left by the BIOS */
if (crtc->active && !transcoder_is_dsi(cpu_transcoder)) {
if (INTEL_GEN(dev_priv) >= 9 ||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder);
u32 val;

if (transcoder_is_dsi(cpu_transcoder))
return;

val = I915_READ(reg);
val &= ~HSW_FRAME_START_DELAY_MASK;
val |= HSW_FRAME_START_DELAY(0);
I915_WRITE(reg, val);
} else {
i915_reg_t reg = PIPECONF(cpu_transcoder);
u32 val;

val = I915_READ(reg);
val &= ~PIPECONF_FRAME_START_DELAY_MASK;
val |= PIPECONF_FRAME_START_DELAY(0);
I915_WRITE(reg, val);
}

if (!crtc_state->has_pch_encoder)
return;

if (HAS_PCH_IBX(dev_priv)) {
i915_reg_t reg = PCH_TRANSCONF(crtc->pipe);
u32 val;

val = I915_READ(reg);
val &= ~TRANS_FRAME_START_DELAY_MASK;
val |= TRANS_FRAME_START_DELAY(0);
I915_WRITE(reg, val);
} else {
i915_reg_t reg = TRANS_CHICKEN2(crtc->pipe);
u32 val;

I915_WRITE(reg,
I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
val = I915_READ(reg);
val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
I915_WRITE(reg, val);
}
}

static void intel_sanitize_crtc(struct intel_crtc *crtc,
struct drm_modeset_acquire_ctx *ctx)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);

if (crtc_state->hw.active) {
struct intel_plane *plane;

/* Clear any frame start delays used for debugging left by the BIOS */
intel_sanitize_frame_start_delay(crtc_state);

/* Disable everything but the primary plane */
for_each_intel_plane_on_crtc(dev, crtc, plane) {
const struct intel_plane_state *plane_state =
Expand Down
12 changes: 7 additions & 5 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -5757,7 +5757,8 @@ enum {
#define PIPECONF_DOUBLE_WIDE (1 << 30)
#define I965_PIPECONF_ACTIVE (1 << 30)
#define PIPECONF_DSI_PLL_LOCKED (1 << 29) /* vlv & pipe A only */
#define PIPECONF_FRAME_START_DELAY_MASK (3 << 27)
#define PIPECONF_FRAME_START_DELAY_MASK (3 << 27) /* pre-hsw */
#define PIPECONF_FRAME_START_DELAY(x) ((x) << 27) /* pre-hsw: 0-3 */
#define PIPECONF_SINGLE_WIDE 0
#define PIPECONF_PIPE_UNLOCKED 0
#define PIPECONF_PIPE_LOCKED (1 << 25)
Expand Down Expand Up @@ -7739,6 +7740,8 @@ enum {
[TRANSCODER_B] = _CHICKEN_TRANS_B, \
[TRANSCODER_C] = _CHICKEN_TRANS_C, \
[TRANSCODER_D] = _CHICKEN_TRANS_D))
#define HSW_FRAME_START_DELAY_MASK (3 << 27)
#define HSW_FRAME_START_DELAY(x) ((x) << 27) /* 0-3 */
#define VSC_DATA_SEL_SOFTWARE_CONTROL (1 << 25) /* GLK and CNL+ */
#define DDI_TRAINING_OVERRIDE_ENABLE (1 << 19)
#define DDI_TRAINING_OVERRIDE_VALUE (1 << 18)
Expand Down Expand Up @@ -8457,10 +8460,8 @@ enum {
#define TRANS_STATE_MASK (1 << 30)
#define TRANS_STATE_DISABLE (0 << 30)
#define TRANS_STATE_ENABLE (1 << 30)
#define TRANS_FSYNC_DELAY_HB1 (0 << 27)
#define TRANS_FSYNC_DELAY_HB2 (1 << 27)
#define TRANS_FSYNC_DELAY_HB3 (2 << 27)
#define TRANS_FSYNC_DELAY_HB4 (3 << 27)
#define TRANS_FRAME_START_DELAY_MASK (3 << 27) /* ibx */
#define TRANS_FRAME_START_DELAY(x) ((x) << 27) /* ibx: 0-3 */
#define TRANS_INTERLACE_MASK (7 << 21)
#define TRANS_PROGRESSIVE (0 << 21)
#define TRANS_INTERLACED (3 << 21)
Expand All @@ -8481,6 +8482,7 @@ enum {
#define TRANS_CHICKEN2_TIMING_OVERRIDE (1 << 31)
#define TRANS_CHICKEN2_FDI_POLARITY_REVERSED (1 << 29)
#define TRANS_CHICKEN2_FRAME_START_DELAY_MASK (3 << 27)
#define TRANS_CHICKEN2_FRAME_START_DELAY(x) ((x) << 27) /* 0-3 */
#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER (1 << 26)
#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH (1 << 25)

Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/i915/intel_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -6368,7 +6368,6 @@ static void cpt_init_clock_gating(struct drm_i915_private *dev_priv)
val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
if (dev_priv->vbt.fdi_rx_polarity_inverted)
val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER;
val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH;
I915_WRITE(TRANS_CHICKEN2(pipe), val);
Expand Down

0 comments on commit cc7a4cf

Please sign in to comment.