CHROMIUM: drm/exynos: Always DPMS Off in encoder prepare and train dp link in DPMS On
In drm_crtc_helper_set_mode(), the basic sequence for encoders and crtcs
is:
->prepare()
->mode_set()
->commit()
For other drm drivers, .prepare does dpms(Off), and .commit does dpms(On).
Thus, the intention is for the .mode_set() callback is supposed to operate properly
in the dpms(Off) state.
For some reason, exynos was not doing dpms(Off) in .prepare, but it was
doing the dpms(On) in .commit, before calling an explicit
panel_ops->commit().
However, the dpms(On) in encoder .commit() never actually does anything,
since the .dpms routines call power on/off routines that are smart and
silently ignore requests that don't change the power state.
In particular, this dpms(On) wasn't able to actually commit changes,
such as enabling video and training the DP link. Instead, we were
essentially relying on a explicit call to panel_ops->commit() in
encoder->commit() to do the commit.
Also, this means that when exynos_drm_encoder_mode_set calls
panel_ops->set_mode(), the current dpms/power state is whatever it was
before the call to drm_crtc_helper_set_mode(). This is almost always
DPMS(On).
DP link training uses the AUX channel which is only available when
DPMS(On). A recent change to the dp driver to move link training to the
dp panel_ops->mode_set() seemed to work because, as noted above, we are
almost always in DPMS(On) for DP when we do mode_sets.
There is, however, one exception. It is possible for userspace to explicit
turn DPMS(Off) the DP pipe. To save power, for instance. If this is
followed by a suspend/resume cycle, the resume path, will end up
calling DP mode_set() with dpms(Off). This causes a soft lockup since the
AUX channel is not enabled when we try to do link training.
Instead, we just always do DPMS(Off) in .prepare(), get rid of the
explicit DP mode_set(), and let the encoder .commit call our DPMS(On)
which will train the link.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
BUG=chromium:189108
TEST=(1) On daisy:
set_short_powerd_timeouts ; echo 1 > /var/lib/power_manager/disable_idle_suspend
wait ~20 seconds for powerd to turn off the LCD
./run_remote_tests.sh --board=daisy --remote=$IP power_Resume/control$
TEST=(2) Same as (1) but with HDMI monitor attached too
=> In this case powerd will switch to "presentation mode", so the turn
LCD off time is ~45 seconds (and it takes two timeouts).
TEST=(3) suspend_stress_test should survive even after LCD powers off
Change-Id: I3cd09d5b9555a9e05efc5a66478ab86f2216fc6b
Reviewed-on: https://gerrit.chromium.org/gerrit/47753
Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
Tested-by: Daniel Kurtz <djkurtz@chromium.org>
Commit-Queue: Daniel Kurtz <djkurtz@chromium.org>