aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_lspcon.c
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2016-11-21 21:15:04 +0200
committerImre Deak <imre.deak@intel.com>2016-11-23 13:27:29 +0200
commitf2b667b658f998d4bba12ca0204c01f34fdb0321 (patch)
treef3d790136e22a12e70bfc71cc53dfe126a8354c6 /drivers/gpu/drm/i915/intel_lspcon.c
parentdrm/i915: Stop the machine as we install the wedged submit_request handler (diff)
downloadlinux-dev-f2b667b658f998d4bba12ca0204c01f34fdb0321.tar.xz
linux-dev-f2b667b658f998d4bba12ca0204c01f34fdb0321.zip
drm/i915/lspcon: Ensure AUX CH is awake while in DP Sleep state
Some LSPCON adaptors won't properly wake up in response to an AUX request after the adaptor was placed to a DP Sink Sleep state (via writing 0x2 to DP_SET_POWER). Based on the DP 1.4 specification 5.2.5, the sink may place the AUX CH into a low-power state while in Sleep state, but should wake it up in response to an AUX request within 1-20ms (answering with AUX defers while waking it up). As opposed to this at least the ParadTech PS175 adaptor won't fully wake in response to the first I2C-over-AUX access and will occasionally ignore the offset in I2C messages. This can result in accessing the DDC register at offset 0 regardless of the specified offset and the LSPCON detection failing. To fix this do an initial dummy read from the DPCD area. The PS175 will defer this access until it's fully woken (taking ~150ms) making sure the following I2C-over-AUX accesses will work correctly. Cc: Shashank Sharma <shashank.sharma@intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Jani Nikula <jani.nikula@intel.com> Reference: https://bugs.freedesktop.org/show_bug.cgi?id=98353 Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Shashank Sharma <shashank.sharma@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1479755707-29596-2-git-send-email-imre.deak@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/intel_lspcon.c')
-rw-r--r--drivers/gpu/drm/i915/intel_lspcon.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
index daa523410953..50131249d0bf 100644
--- a/drivers/gpu/drm/i915/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/intel_lspcon.c
@@ -77,11 +77,29 @@ static int lspcon_change_mode(struct intel_lspcon *lspcon,
return 0;
}
+static bool lspcon_wake_native_aux_ch(struct intel_lspcon *lspcon)
+{
+ uint8_t rev;
+
+ if (drm_dp_dpcd_readb(&lspcon_to_intel_dp(lspcon)->aux, DP_DPCD_REV,
+ &rev) != 1) {
+ DRM_DEBUG_KMS("Native AUX CH down\n");
+ return false;
+ }
+
+ DRM_DEBUG_KMS("Native AUX CH up, DPCD version: %d.%d\n",
+ rev >> 4, rev & 0xf);
+
+ return true;
+}
+
static bool lspcon_probe(struct intel_lspcon *lspcon)
{
enum drm_dp_dual_mode_type adaptor_type;
struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
+ lspcon_wake_native_aux_ch(lspcon);
+
/* Lets probe the adaptor and check its type */
adaptor_type = drm_dp_dual_mode_detect(adapter);
if (adaptor_type != DRM_DP_DUAL_MODE_LSPCON) {
@@ -132,7 +150,8 @@ static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon)
void lspcon_resume(struct intel_lspcon *lspcon)
{
- lspcon_resume_in_pcon_wa(lspcon);
+ if (lspcon_wake_native_aux_ch(lspcon))
+ lspcon_resume_in_pcon_wa(lspcon);
if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON, true))
DRM_ERROR("LSPCON resume failed\n");