Commit dce56b3c626fb1d533258a624d42a1a3fc17da17

Authored by Paulo Zanoni
Committed by Daniel Vetter
1 parent 0095e6dcd3

drm/i915: save some time when waiting the eDP timings

The eDP spec defines some points where after you do action A, you have
to wait some time before action B. The thing is that in our driver
action B does not happen exactly after action A, but we still use
msleep() calls directly. What this patch does is that we record the
timestamp of when action A happened, then, just before action B, we
look at how much time has passed and only sleep the remaining amount
needed.

With this change, I am able to save about 5-20ms (out of the total
200ms) of the backlight_off delay and completely skip the 1ms
backlight_on delay. The 600ms vdd_off delay doesn't happen during
normal usage anymore due to a previous patch.

v2: - Rename ironlake_wait_jiffies_delay to intel_wait_until_after and
      move it to intel_display.c
    - Fix the msleep call: diff is in jiffies
v3: - Use "tmp_jiffies" so we don't need to worry about the value of
      "jiffies" advancing while we're doing the math.
v4: - Rename function again.
    - Move function to i915_drv.h.
    - Store last_power_cycle at edp_panel_off too.
    - Use msecs_to_jiffies_timeout, then replace the msleep with an
      open-coded version that avoids the extra +1 jiffy.
    - Try to add units to every variable name so we don't confuse
      jiffies with milliseconds.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Showing 3 changed files with 56 additions and 3 deletions Side-by-side Diff

drivers/gpu/drm/i915/i915_drv.h
... ... @@ -2556,5 +2556,34 @@
2556 2556 return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1);
2557 2557 }
2558 2558  
  2559 +/*
  2560 + * If you need to wait X milliseconds between events A and B, but event B
  2561 + * doesn't happen exactly after event A, you record the timestamp (jiffies) of
  2562 + * when event A happened, then just before event B you call this function and
  2563 + * pass the timestamp as the first argument, and X as the second argument.
  2564 + */
  2565 +static inline void
  2566 +wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms)
  2567 +{
  2568 + unsigned long target_jiffies, tmp_jiffies;
  2569 + unsigned int remaining_ms;
  2570 +
  2571 + /*
  2572 + * Don't re-read the value of "jiffies" every time since it may change
  2573 + * behind our back and break the math.
  2574 + */
  2575 + tmp_jiffies = jiffies;
  2576 + target_jiffies = timestamp_jiffies +
  2577 + msecs_to_jiffies_timeout(to_wait_ms);
  2578 +
  2579 + if (time_after(target_jiffies, tmp_jiffies)) {
  2580 + remaining_ms = jiffies_to_msecs((long)target_jiffies -
  2581 + (long)tmp_jiffies);
  2582 + while (remaining_ms)
  2583 + remaining_ms =
  2584 + schedule_timeout_uninterruptible(remaining_ms);
  2585 + }
  2586 +}
  2587 +
2559 2588 #endif
drivers/gpu/drm/i915/intel_dp.c
... ... @@ -1057,10 +1057,27 @@
1057 1057 static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp)
1058 1058 {
1059 1059 DRM_DEBUG_KMS("Wait for panel power cycle\n");
  1060 +
  1061 + /* When we disable the VDD override bit last we have to do the manual
  1062 + * wait. */
  1063 + wait_remaining_ms_from_jiffies(intel_dp->last_power_cycle,
  1064 + intel_dp->panel_power_cycle_delay);
  1065 +
1060 1066 ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
1061 1067 }
1062 1068  
  1069 +static void ironlake_wait_backlight_on(struct intel_dp *intel_dp)
  1070 +{
  1071 + wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
  1072 + intel_dp->backlight_on_delay);
  1073 +}
1063 1074  
  1075 +static void ironlake_edp_wait_backlight_off(struct intel_dp *intel_dp)
  1076 +{
  1077 + wait_remaining_ms_from_jiffies(intel_dp->last_backlight_off,
  1078 + intel_dp->backlight_off_delay);
  1079 +}
  1080 +
1064 1081 /* Read the current pp_control value, unlocking the register if it
1065 1082 * is locked
1066 1083 */
... ... @@ -1147,7 +1164,7 @@
1147 1164 I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
1148 1165  
1149 1166 if ((pp & POWER_TARGET_ON) == 0)
1150   - msleep(intel_dp->panel_power_cycle_delay);
  1167 + intel_dp->last_power_cycle = jiffies;
1151 1168  
1152 1169 intel_runtime_pm_put(dev_priv);
1153 1170 }
... ... @@ -1222,6 +1239,7 @@
1222 1239 POSTING_READ(pp_ctrl_reg);
1223 1240  
1224 1241 ironlake_wait_panel_on(intel_dp);
  1242 + intel_dp->last_power_on = jiffies;
1225 1243  
1226 1244 if (IS_GEN5(dev)) {
1227 1245 pp |= PANEL_POWER_RESET; /* restore panel reset bit */
... ... @@ -1242,6 +1260,8 @@
1242 1260  
1243 1261 DRM_DEBUG_KMS("Turn eDP power off\n");
1244 1262  
  1263 + ironlake_edp_wait_backlight_off(intel_dp);
  1264 +
1245 1265 pp = ironlake_get_pp_control(intel_dp);
1246 1266 /* We need to switch off panel power _and_ force vdd, for otherwise some
1247 1267 * panels get very unhappy and cease to work. */
... ... @@ -1252,6 +1272,7 @@
1252 1272 I915_WRITE(pp_ctrl_reg, pp);
1253 1273 POSTING_READ(pp_ctrl_reg);
1254 1274  
  1275 + intel_dp->last_power_cycle = jiffies;
1255 1276 ironlake_wait_panel_off(intel_dp);
1256 1277 }
1257 1278  
... ... @@ -1273,7 +1294,7 @@
1273 1294 * link. So delay a bit to make sure the image is solid before
1274 1295 * allowing it to appear.
1275 1296 */
1276   - msleep(intel_dp->backlight_on_delay);
  1297 + ironlake_wait_backlight_on(intel_dp);
1277 1298 pp = ironlake_get_pp_control(intel_dp);
1278 1299 pp |= EDP_BLC_ENABLE;
1279 1300  
... ... @@ -1305,7 +1326,7 @@
1305 1326  
1306 1327 I915_WRITE(pp_ctrl_reg, pp);
1307 1328 POSTING_READ(pp_ctrl_reg);
1308   - msleep(intel_dp->backlight_off_delay);
  1329 + intel_dp->last_backlight_off = jiffies;
1309 1330 }
1310 1331  
1311 1332 static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
drivers/gpu/drm/i915/intel_drv.h
... ... @@ -487,6 +487,9 @@
487 487 int backlight_off_delay;
488 488 struct delayed_work panel_vdd_work;
489 489 bool want_panel_vdd;
  490 + unsigned long last_power_cycle;
  491 + unsigned long last_power_on;
  492 + unsigned long last_backlight_off;
490 493 bool psr_setup_done;
491 494 struct intel_connector *attached_connector;
492 495 };