From patchwork Tue Jul 28 16:03:29 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 6887521 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 82188C05AC for ; Tue, 28 Jul 2015 16:03:46 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8B84D205E2 for ; Tue, 28 Jul 2015 16:03:44 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 8CC92205DC for ; Tue, 28 Jul 2015 16:03:43 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0543C6E138; Tue, 28 Jul 2015 09:03:43 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4EC2A6EA49 for ; Tue, 28 Jul 2015 09:03:38 -0700 (PDT) Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id DCF5631B7BC; Tue, 28 Jul 2015 16:03:37 +0000 (UTC) Received: from plouf.banquise.eu.com (ovpn-113-32.phx2.redhat.com [10.3.113.32]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t6SG3Xvf012447; Tue, 28 Jul 2015 12:03:37 -0400 From: Benjamin Tissoires To: Daniel Vetter Date: Tue, 28 Jul 2015 12:03:29 -0400 Message-Id: <1438099409-25456-4-git-send-email-benjamin.tissoires@redhat.com> In-Reply-To: <1438099409-25456-1-git-send-email-benjamin.tissoires@redhat.com> References: <1438099409-25456-1-git-send-email-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 Cc: intel-gfx@lists.freedesktop.org, Benjamin Tissoires , Todd Broch , linux-kernel@vger.kernel.org Subject: [Intel-gfx] [PATCH 3/3] drm/i915: Support DDI lane reversal for DP X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The DP outputs connected through a USB Type-C port can have inverted lanes. To detect that case, we implement autodetection by training only the first lane if it doesn't work, we assume that we need to invert the lanes. Tested on a Chromebook Pixel 2015 (samus) with a USB Type-C to HDMI adapter and a Dell 4K and some various regular monitors. Based on 2 patches from the ChromeOS tree by: Stéphane Marchesin Todd Broch Signed-off-by: Benjamin Tissoires --- drivers/gpu/drm/i915/intel_ddi.c | 13 +++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 50 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 9a40bfb..0b0c1ec 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2249,6 +2249,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) enum port port = intel_ddi_get_encoder_port(intel_encoder); int type = intel_encoder->type; int hdmi_level; + bool reversed = false; if (type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -2295,8 +2296,20 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + if (IS_BROADWELL(dev) && type == INTEL_OUTPUT_DISPLAYPORT) { + intel_ddi_init_dp_buf_reg(intel_encoder); + reversed = intel_dp_is_reversed(intel_dp); + } + intel_ddi_init_dp_buf_reg(intel_encoder); + if (IS_BROADWELL(dev)) { + if (reversed) + intel_dp->DP |= DDI_BUF_PORT_REVERSAL; + else + intel_dp->DP &= ~DDI_BUF_PORT_REVERSAL; + } + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_start_link_train(intel_dp); intel_dp_complete_link_train(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b740987..18280cc 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3820,6 +3820,42 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) intel_dp->DP = DP; } +bool intel_dp_is_reversed(struct intel_dp *intel_dp) +{ + struct drm_encoder *encoder = &dp_to_dig_port(intel_dp)->base.base; + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t DP = intel_dp->DP; + + /* + * Train with 1 lane. There is no guarantee that the monitor supports + * 2 or 4 lanes, and we wouldn't see any asymetricity with 4 lanes. + */ + const uint8_t lane_count = 1; + bool reversed; + + if (!HAS_DDI(dev)) + return false; + + DP &= ~(DDI_BUF_PORT_REVERSAL | DDI_PORT_WIDTH(4)); + DP |= DDI_PORT_WIDTH(lane_count); + + I915_WRITE(intel_dp->output_reg, DP); + POSTING_READ(intel_dp->output_reg); + udelay(600); + + if (!_intel_dp_start_link_train(intel_dp, lane_count, &DP, true)) + return true; + + reversed = !_intel_dp_complete_link_train(intel_dp, lane_count, &DP, true); + + /* clear training, we had only one lane */ + intel_dp->train_set_valid = false; + + return reversed; + +} + void intel_dp_stop_link_train(struct intel_dp *intel_dp) { intel_dp_set_link_train(intel_dp, &intel_dp->DP, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 320c9e6..cba00c6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1169,6 +1169,7 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc); bool intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); bool intel_dp_is_edp(struct drm_device *dev, enum port port); +bool intel_dp_is_reversed(struct intel_dp *intel_dp); enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd); void intel_edp_backlight_on(struct intel_dp *intel_dp);