From patchwork Mon Feb 3 15:13:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 11362967 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C69DE14B4 for ; Mon, 3 Feb 2020 15:15:04 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AE800218AC for ; Mon, 3 Feb 2020 15:15:04 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org AE800218AC Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 12DF66EC53; Mon, 3 Feb 2020 15:15:03 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by gabe.freedesktop.org (Postfix) with ESMTPS id C01546EC52; Mon, 3 Feb 2020 15:15:00 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Feb 2020 07:15:00 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,398,1574150400"; d="scan'208";a="225194522" Received: from stinkbox.fi.intel.com (HELO stinkbox) ([10.237.72.174]) by fmsmga008.fm.intel.com with SMTP; 03 Feb 2020 07:14:57 -0800 Received: by stinkbox (sSMTP sendmail emulation); Mon, 03 Feb 2020 17:14:57 +0200 From: Ville Syrjala To: dri-devel@lists.freedesktop.org Subject: [PATCH 24/26] drm/i915: Decouple DP++ from the HDMI code Date: Mon, 3 Feb 2020 17:13:41 +0200 Message-Id: <20200203151343.14378-25-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200203151343.14378-1-ville.syrjala@linux.intel.com> References: <20200203151343.14378-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Ville Syrjälä Decouple the DP dual mode adaptor stuff from the HDMI code so that we can try to use it for DP branch downstream facing HDMI ports as well. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_ddi.c | 6 +- .../drm/i915/display/intel_display_types.h | 12 ++- drivers/gpu/drm/i915/display/intel_hdmi.c | 94 ++++++++++--------- drivers/gpu/drm/i915/display/intel_hdmi.h | 9 +- 4 files changed, 72 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 3d1393ff6435..92c280905f31 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3598,7 +3598,8 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, int level = intel_ddi_hdmi_level(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); + intel_dp_dual_mode_set_tmds_output(encoder, + &intel_hdmi->dp_dual_mode, true); intel_ddi_clk_select(encoder, crtc_state); intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); @@ -3778,7 +3779,8 @@ static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder, intel_ddi_clk_disable(encoder); - intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); + intel_dp_dual_mode_set_tmds_output(encoder, + &intel_hdmi->dp_dual_mode, false); } static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 00471791d772..0d135859e9d4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -46,6 +46,7 @@ #include "i915_drv.h" #include "intel_de.h" +struct i2c_adapter; struct drm_printer; struct __intel_global_objs_state; @@ -1150,15 +1151,18 @@ struct cxsr_latency { #define to_intel_plane_state(x) container_of(x, struct intel_plane_state, uapi) #define intel_fb_obj(x) ((x) ? to_intel_bo((x)->obj[0]) : NULL) +struct intel_dp_dual_mode { + struct i2c_adapter *adapter; + int max_tmds_clock; + enum drm_dp_dual_mode_type type; +}; + struct intel_hdmi { i915_reg_t hdmi_reg; int ddc_bus; - struct { - enum drm_dp_dual_mode_type type; - int max_tmds_clock; - } dp_dual_mode; bool has_hdmi_sink; bool has_audio; + struct intel_dp_dual_mode dp_dual_mode; struct intel_connector *attached_connector; struct cec_notifier *cec_notifier; }; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 9e0316f6eb3f..ad8e974585b9 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1249,20 +1249,19 @@ static void hsw_set_infoframes(struct intel_encoder *encoder, &crtc_state->infoframes.drm); } -void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable) +void intel_dp_dual_mode_set_tmds_output(struct intel_encoder *encoder, + struct intel_dp_dual_mode *dp_dual_mode, + bool enable) { - struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi)); - struct i2c_adapter *adapter = - intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); - - if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI) + if (dp_dual_mode->type < DRM_DP_DUAL_MODE_TYPE2_DVI) return; - DRM_DEBUG_KMS("%s DP dual mode adaptor TMDS output\n", + DRM_DEBUG_KMS("[ENCODER:%d:%s] %s DP dual mode adaptor TMDS output\n", + encoder->base.base.id, encoder->base.name, enable ? "Enabling" : "Disabling"); - drm_dp_dual_mode_set_tmds_output(hdmi->dp_dual_mode.type, - adapter, enable); + drm_dp_dual_mode_set_tmds_output(dp_dual_mode->type, + dp_dual_mode->adapter, enable); } static int intel_hdmi_hdcp_read(struct intel_digital_port *intel_dig_port, @@ -1750,7 +1749,8 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; u32 hdmi_val; - intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); + intel_dp_dual_mode_set_tmds_output(encoder, + &intel_hdmi->dp_dual_mode, true); hdmi_val = SDVO_ENCODING_HDMI; if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range) @@ -2064,7 +2064,8 @@ static void intel_disable_hdmi(struct intel_encoder *encoder, false, old_crtc_state, old_conn_state); - intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); + intel_dp_dual_mode_set_tmds_output(encoder, + &intel_hdmi->dp_dual_mode, false); } static void g4x_disable_hdmi(struct intel_encoder *encoder, @@ -2519,28 +2520,24 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, } static void -intel_hdmi_unset_edid(struct drm_connector *connector) +intel_hdmi_unset_edid(struct intel_connector *connector) { - struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)); + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_audio = false; - intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; - intel_hdmi->dp_dual_mode.max_tmds_clock = 0; + intel_dp_dual_mode_reset(&intel_hdmi->dp_dual_mode); - kfree(to_intel_connector(connector)->detect_edid); - to_intel_connector(connector)->detect_edid = NULL; + kfree(connector->detect_edid); + connector->detect_edid = NULL; } -static void -intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) +void intel_dp_dual_mode_detect(struct intel_connector *connector, + struct intel_dp_dual_mode *dp_dual_mode, + bool assume_type1_dvi) { - struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)); - enum port port = hdmi_to_dig_port(hdmi)->base.port; - struct i2c_adapter *adapter = - intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); + struct i2c_adapter *adapter = dp_dual_mode->adapter; enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(adapter); /* @@ -2559,9 +2556,9 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) /* An overridden EDID imply that we want this port for testing. * Make sure not to set limits for that port. */ - if (has_edid && !connector->override_edid && - intel_bios_is_port_dp_dual_mode(dev_priv, port)) { - DRM_DEBUG_KMS("Assuming DP dual mode adaptor presence based on VBT\n"); + if (assume_type1_dvi) { + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Assuming type1 DVI DP dual mode adaptor presence\n", + connector->base.base.id, connector->base.name); type = DRM_DP_DUAL_MODE_TYPE1_DVI; } else { type = DRM_DP_DUAL_MODE_NONE; @@ -2571,20 +2568,28 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) if (type == DRM_DP_DUAL_MODE_NONE) return; - hdmi->dp_dual_mode.type = type; - hdmi->dp_dual_mode.max_tmds_clock = + dp_dual_mode->type = type; + dp_dual_mode->max_tmds_clock = drm_dp_dual_mode_max_tmds_clock(type, adapter); - DRM_DEBUG_KMS("DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n", + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n", + connector->base.base.id, connector->base.name, drm_dp_get_dual_mode_type_name(type), - hdmi->dp_dual_mode.max_tmds_clock); + dp_dual_mode->max_tmds_clock); +} + +void intel_dp_dual_mode_reset(struct intel_dp_dual_mode *dp_dual_mode) +{ + dp_dual_mode->type = DRM_DP_DUAL_MODE_NONE; + dp_dual_mode->max_tmds_clock = 0; } static bool -intel_hdmi_set_edid(struct drm_connector *connector) +intel_hdmi_set_edid(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)); + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); + enum port port = hdmi_to_dig_port(intel_hdmi)->base.port; intel_wakeref_t wakeref; struct edid *edid; bool connected = false; @@ -2594,20 +2599,22 @@ intel_hdmi_set_edid(struct drm_connector *connector) i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); - edid = drm_get_edid(connector, i2c); + edid = drm_get_edid(&connector->base, i2c); if (!edid && !intel_gmbus_is_forced_bit(i2c)) { DRM_DEBUG_KMS("HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n"); intel_gmbus_force_bit(i2c, true); - edid = drm_get_edid(connector, i2c); + edid = drm_get_edid(&connector->base, i2c); intel_gmbus_force_bit(i2c, false); } - intel_hdmi_dp_dual_mode_detect(connector, edid != NULL); + intel_dp_dual_mode_detect(connector, &intel_hdmi->dp_dual_mode, + edid && !connector->base.override_edid && + intel_bios_is_port_dp_dual_mode(dev_priv, port)); intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref); - to_intel_connector(connector)->detect_edid = edid; + connector->detect_edid = edid; if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { intel_hdmi->has_audio = drm_detect_monitor_audio(edid); intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); @@ -2638,9 +2645,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) !intel_digital_port_connected(encoder)) goto out; - intel_hdmi_unset_edid(connector); + intel_hdmi_unset_edid(to_intel_connector(connector)); - if (intel_hdmi_set_edid(connector)) + if (intel_hdmi_set_edid(to_intel_connector(connector))) status = connector_status_connected; out: @@ -2664,12 +2671,12 @@ intel_hdmi_force(struct drm_connector *connector) DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); - intel_hdmi_unset_edid(connector); + intel_hdmi_unset_edid(to_intel_connector(connector)); if (connector->status != connector_status_connected) return; - intel_hdmi_set_edid(connector); + intel_hdmi_set_edid(to_intel_connector(connector)); } static int intel_hdmi_get_modes(struct drm_connector *connector) @@ -3188,6 +3195,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) connector->ycbcr_420_allowed = true; + intel_hdmi->dp_dual_mode.adapter = + intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); + intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); if (HAS_DDI(dev_priv)) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h index 52cea8beafbb..e6f7047697ff 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.h +++ b/drivers/gpu/drm/i915/display/intel_hdmi.h @@ -18,6 +18,7 @@ struct drm_encoder; struct drm_i915_private; struct intel_connector; struct intel_digital_port; +struct intel_dp_dual_mode; struct intel_encoder; struct intel_crtc_state; struct intel_hdmi; @@ -37,7 +38,13 @@ bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, struct drm_connector *connector, bool high_tmds_clock_ratio, bool scrambling); -void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); +void intel_dp_dual_mode_detect(struct intel_connector *connector, + struct intel_dp_dual_mode *dp_dual_mode, + bool assume_type1_dvi); +void intel_dp_dual_mode_reset(struct intel_dp_dual_mode *dp_dual_mode); +void intel_dp_dual_mode_set_tmds_output(struct intel_encoder *encodr, + struct intel_dp_dual_mode *dp_dual_mode, + bool enable); void intel_infoframe_init(struct intel_digital_port *intel_dig_port); u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state);