Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 345162
b: refs/heads/master
c: 82ed61f
h: refs/heads/master
v: v3
  • Loading branch information
Daniel Vetter committed Oct 23, 2012
1 parent 134b4e3 commit a26de1d
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 12 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: 2d354c347257287ec00b2e6e26a4d209e348cf7d
refs/heads/master: 82ed61fa1a4e08d5f9e86fb1b715b50ed678b6ac
5 changes: 5 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -4010,6 +4010,11 @@
#define PANEL_LIGHT_ON_DELAY_SHIFT 0

#define PCH_PP_OFF_DELAYS 0xc720c
#define PANEL_POWER_PORT_SELECT_MASK (0x3 << 30)
#define PANEL_POWER_PORT_LVDS (0 << 30)
#define PANEL_POWER_PORT_DP_A (1 << 30)
#define PANEL_POWER_PORT_DP_C (2 << 30)
#define PANEL_POWER_PORT_DP_D (3 << 30)
#define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000)
#define PANEL_POWER_DOWN_DELAY_SHIFT 16
#define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff)
Expand Down
71 changes: 60 additions & 11 deletions trunk/drivers/gpu/drm/i915/intel_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2633,20 +2633,18 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)

/* Cache some DPCD data in the eDP case */
if (is_edp(intel_dp)) {
struct edp_power_seq cur, vbt;
u32 pp_on, pp_off, pp_div;
struct edp_power_seq cur, vbt, spec, final;
u32 pp_on, pp_off, pp_div, pp;

/* Workaround: Need to write PP_CONTROL with the unlock key as
* the very first thing. */
pp = ironlake_get_pp_control(dev_priv);
I915_WRITE(PCH_PP_CONTROL, pp);

pp_on = I915_READ(PCH_PP_ON_DELAYS);
pp_off = I915_READ(PCH_PP_OFF_DELAYS);
pp_div = I915_READ(PCH_PP_DIVISOR);

if (!pp_on || !pp_off || !pp_div) {
DRM_INFO("bad panel power sequencing delays, disabling panel\n");
intel_dp_encoder_destroy(&intel_dp->base.base);
intel_dp_destroy(&intel_connector->base);
return;
}

/* Pull timing values out of registers */
cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
PANEL_POWER_UP_DELAY_SHIFT;
Expand All @@ -2668,23 +2666,74 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)

vbt = dev_priv->edp.pps;

/* Upper limits from eDP 1.3 spec. Note that we use the clunky
* units of our hw here, which are all in 100usec. */
spec.t1_t3 = 210 * 10;
spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */
spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */
spec.t10 = 500 * 10;
/* This one is special and actually in units of 100ms, but zero
* based in the hw (so we need to add 100 ms). But the sw vbt
* table multiplies it with 1000 to make it in units of 100usec,
* too. */
spec.t11_t12 = (510 + 100) * 10;

DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12);

#define get_delay(field) ((max(cur.field, vbt.field) + 9) / 10)

/* Use the max of the register settings and vbt. If both are
* unset, fall back to the spec limits. */
#define assign_final(field) final.field = (max(cur.field, vbt.field) == 0 ? \
spec.field : \
max(cur.field, vbt.field))
assign_final(t1_t3);
assign_final(t8);
assign_final(t9);
assign_final(t10);
assign_final(t11_t12);
#undef assign_final

#define get_delay(field) (DIV_ROUND_UP(final.field, 10))
intel_dp->panel_power_up_delay = get_delay(t1_t3);
intel_dp->backlight_on_delay = get_delay(t8);
intel_dp->backlight_off_delay = get_delay(t9);
intel_dp->panel_power_down_delay = get_delay(t10);
intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
#undef get_delay

/* And finally store the new values in the power sequencer. */
pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
(final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
(final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
pp_div = (pp_div & PP_REFERENCE_DIVIDER_MASK) |
(DIV_ROUND_UP(final.t11_t12, 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT);

/* Haswell doesn't have any port selection bits for the panel
* power sequence any more. */
if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
if (is_cpu_edp(intel_dp))
pp_on |= PANEL_POWER_PORT_DP_A;
else
pp_on |= PANEL_POWER_PORT_DP_D;
}

I915_WRITE(PCH_PP_ON_DELAYS, pp_on);
I915_WRITE(PCH_PP_OFF_DELAYS, pp_off);
I915_WRITE(PCH_PP_DIVISOR, pp_div);


DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
intel_dp->panel_power_cycle_delay);

DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);

DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
I915_READ(PCH_PP_ON_DELAYS),
I915_READ(PCH_PP_OFF_DELAYS),
I915_READ(PCH_PP_DIVISOR));
}

intel_dp_i2c_init(intel_dp, intel_connector, name);
Expand Down

0 comments on commit a26de1d

Please sign in to comment.